From 7c72a6e497cafc26be1a17bc89709525f85bc6d6 Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Tue, 14 Jul 2026 18:35:28 -0700 Subject: [PATCH] Create nbri_ehr module (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create nbri_ehr module as a renamed copy of nirc_ehr Seeds the new nbriEHRModules repository from the nircEHRModules module tree, with every occurrence of nirc replaced by nbri (casing-matched: NIRC→NBRI, Nirc→Nbri, nirc→nbri) in file contents, file names, and directory names. Also carries over the nircEHRModules versions of the GitHub workflow files (adding permissions blocks) and .gitignore (ignoring referenceStudy ETL logs). * Address PR review feedback on initial nbri_ehr module Remove the ETL surface: etls/ definitions, dbo source queries, the CasesTemp staging table, the casesSource/casesTemp staging pieces, and the now-unreferenced NBRIUserCreateTransform column transform. Remove the Orchard/HL7 integration: NBRIOrchardFileGenerator, the orchardData and orchardIdsForTaskid queries, the NBRIOrchardFileLocation module property, the trigger helper method and its JS trigger call sites, and the Selenium test coverage. Drop the 250 building/area-specific .qview.xml saved views, combine the two DB scripts into nbri_ehr-0.000-25.001.sql, and remove ull-logo-main-subsite.png along with its page references. Rename NBRI_EHRSchema.get_instance() to getInstance(), remove the unused category param from canCloseCase(), remove the duplicate CagematesDemographicsProvider registration, and guard isProcedureOrderEntered() against missing rows and null qcstate. Replace leftover NIRC branding (page headings, folder type description) with NBRI, normalize copyright headers to 2026, delete datasetBirth.tsv~, gitignore folder_load logs, and bump actions/checkout to v4. * Stabilize NBRI_EHRTest UI test; fix pairing_formation_types lookup Fix NBRI_EHRTest failures: resolve the vet-tech role by class name (NBRIEHRVetTechRole) since its "EHR Veterinarian Technician" display name collides with NIRC's role and can otherwise assign the wrong module's role (hiding the necropsy-review button); re-assert form fields that get dropped when EHR form sections rebuild (case Subjective, behavior-case Remark, Clinical Case Problem Area) so lingering required/comment warnings don't block submit; set the medication-order Ordered By directly in the grid instead of via the bulk-edit combo, which trips an Ext4 onTypeAhead null client error that can leave the field unset; and scope the active-clinical-cases assertion to the test animal so other tests' open cases don't inflate the count. Also correct the pairing_formation_types row in editable_lookups.tsv to the standard column layout (Behavior category, proper label and description). --- .github/workflows/branch_release.yml | 8 +- .github/workflows/merge_release.yml | 8 +- .github/workflows/validate_pr.yml | 5 +- .gitignore | 7 +- build.gradle | 27 + gradle.properties | 1 + nbri_ehr/build.gradle | 32 + nbri_ehr/module.properties | 2 + .../resources/data/abdominal_obs_types.tsv | 8 + .../data/abnormal_behavior_types.tsv | 7 + nbri_ehr/resources/data/acquisition_type.tsv | 6 + nbri_ehr/resources/data/activity.tsv | 7 + nbri_ehr/resources/data/ageclass.tsv | 79 + nbri_ehr/resources/data/alias_category.tsv | 5 + nbri_ehr/resources/data/alopecia_regrowth.tsv | 4 + nbri_ehr/resources/data/alopecia_score.tsv | 6 + nbri_ehr/resources/data/alopecia_type.tsv | 10 + nbri_ehr/resources/data/amount_units.tsv | 14 + nbri_ehr/resources/data/app_score.tsv | 6 + nbri_ehr/resources/data/arrival_type.tsv | 3 + nbri_ehr/resources/data/att_score.tsv | 6 + .../resources/data/bandage_observations.tsv | 4 + nbri_ehr/resources/data/bcs_score.tsv | 10 + .../resources/data/behavior_abnormality.tsv | 7 + .../resources/data/behavior_mgmt_codes.tsv | 4 + nbri_ehr/resources/data/behavior_types.tsv | 6 + nbri_ehr/resources/data/blood_draw_reason.tsv | 3 + .../resources/data/blood_draw_tube_type.tsv | 5 + nbri_ehr/resources/data/blood_sample_type.tsv | 3 + .../resources/data/blood_tube_volumes.tsv | 8 + nbri_ehr/resources/data/cage_type.tsv | 8 + .../data/calculated_status_codes.tsv | 7 + .../resources/data/capillary_refill_time.tsv | 3 + nbri_ehr/resources/data/card_format.tsv | 4 + .../resources/data/census_activity_status.tsv | 4 + nbri_ehr/resources/data/conc_units.tsv | 18 + nbri_ehr/resources/data/cost_type.tsv | 3 + nbri_ehr/resources/data/country.tsv | 9 + nbri_ehr/resources/data/country_category.tsv | 3 + .../resources/data/daily_enrich_codes.tsv | 13 + nbri_ehr/resources/data/data_category.tsv | 5 + nbri_ehr/resources/data/death_reason.tsv | 6 + nbri_ehr/resources/data/delivery_state.tsv | 5 + nbri_ehr/resources/data/dental_obs.tsv | 7 + nbri_ehr/resources/data/derm_obs.tsv | 6 + nbri_ehr/resources/data/divider_types.tsv | 6 + nbri_ehr/resources/data/dosage_units.tsv | 14 + nbri_ehr/resources/data/editable_lookups.tsv | 140 ++ nbri_ehr/resources/data/esig_events.tsv | 16 + nbri_ehr/resources/data/euthanasia_type.tsv | 5 + nbri_ehr/resources/data/exam_findings.tsv | 3 + .../resources/data/exemption_category.tsv | 9 + nbri_ehr/resources/data/expense_class.tsv | 32 + nbri_ehr/resources/data/fecal_smear_score.tsv | 6 + nbri_ehr/resources/data/feed_assess_types.tsv | 4 + nbri_ehr/resources/data/gender_codes.tsv | 4 + nbri_ehr/resources/data/general_obs.tsv | 7 + nbri_ehr/resources/data/genitourinary_obs.tsv | 7 + .../resources/data/geographic_origins.tsv | 32 + nbri_ehr/resources/data/hernia_types.tsv | 5 + nbri_ehr/resources/data/housing_reason.tsv | 25 + nbri_ehr/resources/data/hyd_score.tsv | 7 + nbri_ehr/resources/data/id_history_type.tsv | 6 + nbri_ehr/resources/data/incision_score.tsv | 8 + nbri_ehr/resources/data/indoor_outdoor.tsv | 4 + nbri_ehr/resources/data/lameness.tsv | 5 + nbri_ehr/resources/data/lookup_sets.tsv | 118 ++ nbri_ehr/resources/data/lookupsManifest.tsv | 131 ++ .../resources/data/lookupsManifestTest.tsv | 133 ++ nbri_ehr/resources/data/mens_score.tsv | 4 + nbri_ehr/resources/data/mucous_membranes.tsv | 7 + .../data/musculoskeletal_observations.tsv | 8 + .../data/necropsy_disposition_codes.tsv | 7 + .../resources/data/necropsy_exam_reason.tsv | 4 + .../data/necropsy_organ_appearance.tsv | 3 + .../resources/data/necropsy_organ_systems.tsv | 10 + .../data/necropsy_physical_condition.tsv | 4 + .../data/necropsy_specimen_condition.tsv | 4 + nbri_ehr/resources/data/necropsy_tissue.tsv | 17 + .../data/neurologic_observations.tsv | 8 + .../resources/data/nhp_training_reason.tsv | 6 + .../resources/data/nhp_training_result.tsv | 4 + nbri_ehr/resources/data/nhp_training_type.tsv | 5 + nbri_ehr/resources/data/normal_abnormal.tsv | 4 + .../resources/data/normal_abnormal_only.tsv | 3 + nbri_ehr/resources/data/numeric_unit.tsv | 91 + nbri_ehr/resources/data/observation_areas.tsv | 34 + nbri_ehr/resources/data/observation_types.tsv | 55 + .../resources/data/obstetric_observations.tsv | 9 + .../resources/data/ocular_observations.tsv | 8 + .../data/pairing_formation_types.tsv | 7 + nbri_ehr/resources/data/pairing_goal.tsv | 5 + .../resources/data/pairing_observation.tsv | 4 + nbri_ehr/resources/data/pairing_reason.tsv | 9 + .../data/pairing_separation_reason.tsv | 8 + nbri_ehr/resources/data/preferences.tsv | 4 + nbri_ehr/resources/data/pregnancy_result.tsv | 3 + .../resources/data/problem_list_category.tsv | 14 + .../data/problem_list_subcategory.tsv | 75 + .../resources/data/procedure_category.tsv | 5 + nbri_ehr/resources/data/procedures.tsv | 130 ++ nbri_ehr/resources/data/protocol_category.tsv | 3 + nbri_ehr/resources/data/protocol_state.tsv | 7 + nbri_ehr/resources/data/protocol_type.tsv | 6 + nbri_ehr/resources/data/qualifier.tsv | 54 + nbri_ehr/resources/data/questionnaire.tsv | 4 + nbri_ehr/resources/data/rectal_prolapse.tsv | 3 + .../data/regulatory_stress_levels.tsv | 6 + nbri_ehr/resources/data/req_order_state.tsv | 6 + nbri_ehr/resources/data/req_order_type.tsv | 5 + .../data/respiratory_observations.tsv | 9 + nbri_ehr/resources/data/routes.tsv | 17 + nbri_ehr/resources/data/sib_score.tsv | 8 + nbri_ehr/resources/data/snomed.tsv | 357 ++++ nbri_ehr/resources/data/source.tsv | 108 ++ nbri_ehr/resources/data/species.tsv | 7 + nbri_ehr/resources/data/species_codes.tsv | 7 + nbri_ehr/resources/data/stool_score.tsv | 7 + nbri_ehr/resources/data/stool_types.tsv | 10 + nbri_ehr/resources/data/temperament.tsv | 5 + nbri_ehr/resources/data/testicular_volume.tsv | 13 + .../resources/data/treatment_frequency.tsv | 12 + .../data/treatment_frequency_times.tsv | 18 + .../data/vaginal_uterine_prolapse.tsv | 3 + .../resources/data/vendor_approval_code.tsv | 4 + .../data/vendor_production_location.tsv | 47 + nbri_ehr/resources/data/volume_units.tsv | 16 + nbri_ehr/resources/data/weight_ranges.tsv | 3 + nbri_ehr/resources/data/wound_severity.tsv | 6 + .../resources/data/wound_status_behavior.tsv | 5 + .../resources/data/wound_status_clinical.tsv | 11 + nbri_ehr/resources/data/yes_no_only.tsv | 3 + nbri_ehr/resources/data/yes_no_order.tsv | 4 + .../domain-templates/ehr.template.xml | 125 ++ .../domain-templates/ehr_lookups.template.xml | 52 + .../folderTypes/NBRI_EHR.folderType.xml | 70 + nbri_ehr/resources/module.xml | 8 + .../resources/queries/ehr/activeProtocols.sql | 7 + .../resources/queries/ehr/my_tasks.query.xml | 65 + nbri_ehr/resources/queries/ehr/my_tasks.sql | 28 + .../resources/queries/ehr/my_tasks/.qview.xml | 15 + .../ehr/my_tasks/Active Tasks.qview.xml | 18 + .../ehr/my_tasks/Review Required.qview.xml | 18 + .../queries/ehr/observation_types.query.xml | 17 + nbri_ehr/resources/queries/ehr/project.js | 32 + .../resources/queries/ehr/project.query.xml | 75 + .../resources/queries/ehr/project/.qview.xml | 8 + nbri_ehr/resources/queries/ehr/protocol.js | 37 + .../resources/queries/ehr/protocol.query.xml | 91 + .../resources/queries/ehr/protocol/.qview.xml | 41 + .../ehr/protocolActiveAnimals.query.xml | 29 + .../queries/ehr/protocolActiveAnimals.sql | 21 + .../queries/ehr/protocolAnimals.query.xml | 43 + .../resources/queries/ehr/protocolAnimals.sql | 22 + .../queries/ehr/protocolHistoricAnimals.sql | 26 + .../protocolTotalAnimalsBySpecies.query.xml | 36 + .../ehr/protocolTotalAnimalsBySpecies.sql | 18 + .../queries/ehr/protocol_counts.query.xml | 30 + .../queries/ehr/protocol_counts/.qview.xml | 9 + .../resources/queries/ehr/tasks/.qview.xml | 19 + .../queries/ehr/tasks/Active Tasks.qview.xml | 8 + .../ehr/tasks/Review Required.qview.xml | 22 + .../queries/ehr_lookups/ageclass.query.xml | 45 + .../queries/ehr_lookups/areas/.qview.xml | 7 + .../queries/ehr_lookups/buildings.js | 53 + .../queries/ehr_lookups/buildings.query.xml | 31 + .../queries/ehr_lookups/buildings/.qview.xml | 6 + .../resources/queries/ehr_lookups/cage.js | 50 + .../queries/ehr_lookups/cage.query.xml | 29 + .../queries/ehr_lookups/cage/.qview.xml | 12 + .../queries/ehr_lookups/country.query.xml | 20 + .../resources/queries/ehr_lookups/floors.js | 53 + .../queries/ehr_lookups/floors.query.xml | 28 + .../queries/ehr_lookups/floors/.qview.xml | 6 + .../queries/ehr_lookups/procedures/.qview.xml | 7 + .../ehr_lookups/roomUtilization.query.xml | 22 + .../queries/ehr_lookups/roomUtilization.sql | 16 + .../roomUtilizationByBuilding.query.xml | 81 + .../ehr_lookups/roomUtilizationByBuilding.sql | 30 + .../resources/queries/ehr_lookups/rooms.js | 54 + .../queries/ehr_lookups/rooms.query.xml | 24 + .../queries/ehr_lookups/rooms/.qview.xml | 6 + .../queries/ehr_lookups/snomed.query.xml | 9 + .../ehr_lookups/species_codes.query.xml | 19 + .../vendor_production_location.query.xml | 19 + .../queries/nbri_ehr/Account.query.xml | 48 + .../queries/nbri_ehr/AnimalDelivery.query.xml | 86 + .../nbri_ehr/AnimalDeliveryEsig.query.xml | 36 + .../queries/nbri_ehr/AnimalReqOrder.query.xml | 135 ++ .../nbri_ehr/AnimalReqOrderEsig.query.xml | 36 + .../queries/nbri_ehr/AnimalShipment.query.xml | 42 + .../queries/nbri_ehr/AnimalVendor.query.xml | 29 + .../queries/nbri_ehr/AnimalVendor/.qview.xml | 20 + .../queries/nbri_ehr/CageCard.query.xml | 56 + .../nbri_ehr/CageCardHistory.query.xml | 65 + .../queries/nbri_ehr/DeletedRecord.query.xml | 24 + .../queries/nbri_ehr/Department.query.xml | 25 + .../queries/nbri_ehr/IdHistory.query.xml | 29 + .../resources/queries/nbri_ehr/Lot.query.xml | 20 + .../queries/nbri_ehr/ProtocolEsig.query.xml | 31 + .../nbri_ehr/ProtocolProcedures.query.xml | 21 + .../queries/nbri_ehr/ProtocolStress.query.xml | 21 + .../queries/nbri_ehr/QuestionResponse.js | 35 + .../nbri_ehr/QuestionResponse.query.xml | 38 + .../resources/queries/nbri_ehr/dateRange.sql | 25 + .../queries/nbri_ehr/locationTypes/.qview.xml | 5 + .../queries/nbri_ehr/locations.query.xml | 19 + .../queries/nbri_ehr/locations/.qview.xml | 6 + .../nbri_ehr/locationsMapping.query.xml | 28 + .../nbri_ehr/locationsMapping/.qview.xml | 7 + .../queries/nbri_ehr/necropsyTasks.query.xml | 28 + .../queries/nbri_ehr/necropsyTasks.sql | 26 + .../queries/nbri_ehr/necropsyTasks/.qview.xml | 28 + .../queries/nbri_ehr/staff.query.xml | 128 ++ .../queries/nbri_ehr/stress.query.xml | 20 + .../queries/study/AcquisitionReport.sql | 14 + .../study/AcquisitionReportBySpecies.sql | 18 + .../queries/study/BehaviorClinRemarks.sql | 7 + .../study/BehaviorClinRemarks/.qview.xml | 16 + .../queries/study/ClinicalClinRemarks.sql | 7 + .../study/ClinicalClinRemarks/.qview.xml | 20 + .../study/CurrentProtocolProjectReport.sql | 17 + nbri_ehr/resources/queries/study/MHC.js | 7 + .../resources/queries/study/MHC.query.xml | 14 + nbri_ehr/resources/queries/study/Pedigree.sql | 31 + nbri_ehr/resources/queries/study/Weight.js | 91 + .../queries/study/activeAssignments.sql | 22 + .../queries/study/activeBehaviorCases.sql | 7 + .../study/activeBehaviorCases/.qview.xml | 28 + .../queries/study/activeClinicalCases.sql | 7 + .../study/activeClinicalCases/.qview.xml | 28 + .../study/activeProjectsFromHousing.sql | 10 + .../queries/study/activeTreatmentOrders.sql | 25 + nbri_ehr/resources/queries/study/alias.js | 6 + .../resources/queries/study/alias.query.xml | 29 + nbri_ehr/resources/queries/study/aliases.sql | 19 + .../queries/study/alopecia/.qview.xml | 18 + nbri_ehr/resources/queries/study/arrival.js | 176 ++ .../resources/queries/study/arrival.query.xml | 79 + .../queries/study/arrival/.qview.xml | 18 + .../resources/queries/study/assignment.js | 91 + .../queries/study/assignment.query.xml | 28 + .../resources/queries/study/behaviorCases.sql | 7 + .../queries/study/behaviorCases/.qview.xml | 28 + .../queries/study/behaviorObservations.sql | 7 + .../study/behaviorObservations/.qview.xml | 18 + nbri_ehr/resources/queries/study/birth.js | 169 ++ .../resources/queries/study/birth.query.xml | 52 + .../resources/queries/study/blood/.qview.xml | 19 + .../queries/study/bloodDrawChanges.sql | 66 + .../queries/study/breeder/.qview.xml | 15 + nbri_ehr/resources/queries/study/cases.js | 71 + .../resources/queries/study/cases.query.xml | 71 + .../resources/queries/study/cases/.qview.xml | 28 + .../cases/Active Behavior Cases.qview.xml | 29 + .../cases/Active Clinical Cases.qview.xml | 32 + .../study/cases/All Behavior Cases.qview.xml | 28 + .../study/cases/All Clinical Cases.qview.xml | 31 + .../queries/study/chemistryResults.query.xml | 22 + .../queries/study/chemistryResults/.qview.xml | 18 + .../resources/queries/study/clinicalCases.sql | 7 + .../queries/study/clinicalCases/.qview.xml | 28 + .../queries/study/clinicalObservations.sql | 7 + .../study/clinicalObservations/.qview.xml | 17 + .../queries/study/clinical_observations.js | 77 + .../study/clinical_observations.query.xml | 58 + .../study/clinical_observations/.qview.xml | 19 + .../Alopecia Scores.qview.xml | 21 + .../clinical_observations/Behavior.qview.xml | 21 + .../clinical_observations/Clinical.qview.xml | 21 + .../study/clinical_observationsSummary.sql | 29 + .../clinical_observationsSummary/.qview.xml | 18 + .../resources/queries/study/clinremarks.js | 31 + .../queries/study/clinremarks.query.xml | 63 + .../queries/study/clinremarks/.qview.xml | 21 + .../study/clinremarks/Behavior.qview.xml | 19 + .../study/clinremarks/Clinical.qview.xml | 24 + .../colonyPopulationByAgeClass.query.xml | 30 + .../queries/study/colonyPopulationChange.sql | 59 + .../study/colonyPopulationSummary.query.xml | 28 + .../queries/study/currentBloodDraws.sql | 84 + .../queries/study/currentproject.sql | 11 + .../queries/study/deathNotification.sql | 13 + nbri_ehr/resources/queries/study/deaths.js | 180 ++ .../resources/queries/study/deaths.query.xml | 34 + .../resources/queries/study/deaths/.qview.xml | 14 + .../resources/queries/study/demographics.js | 57 + .../queries/study/demographics.query.xml | 112 ++ .../queries/study/demographics/.qview.xml | 23 + .../queries/study/demographicsActiveFlags.sql | 24 + .../demographicsActiveProjectAssignment.sql | 10 + ...graphicsActiveProtocolAssignment.query.xml | 29 + .../demographicsActiveProtocolAssignment.sql | 18 + .../study/demographicsAliases.query.xml | 9 + .../queries/study/demographicsAliases.sql | 11 + .../study/demographicsCagemates.query.xml | 24 + .../queries/study/demographicsCagemates.sql | 33 + .../study/demographicsCurLocation.query.xml | 35 + .../queries/study/demographicsCurLocation.sql | 37 + .../study/demographicsLastProject.query.xml | 13 + .../queries/study/demographicsLastProject.sql | 15 + .../study/demographicsLastProtocol.query.xml | 13 + .../study/demographicsLastProtocol.sql | 15 + .../study/demographicsOffspring.query.xml | 20 + .../queries/study/demographicsOffspring.sql | 21 + .../study/demographicsParents.query.xml | 31 + .../queries/study/demographicsParents.sql | 30 + .../study/demographicsSiblings.query.xml | 44 + .../queries/study/demographicsSiblings.sql | 36 + .../study/demographicsSource.query.xml | 17 + .../queries/study/demographicsSource.sql | 35 + .../demographicsTotalOffspring.query.xml | 34 + .../study/demographicsTotalOffspring.sql | 42 + nbri_ehr/resources/queries/study/departure.js | 31 + .../queries/study/departure.query.xml | 23 + .../queries/study/departure/.qview.xml | 14 + nbri_ehr/resources/queries/study/drug.js | 28 + .../resources/queries/study/drug.query.xml | 111 ++ .../resources/queries/study/drug/.qview.xml | 26 + .../queries/study/drug/Behavior.qview.xml | 28 + .../resources/queries/study/exemptions.js | 6 + .../queries/study/exemptions.query.xml | 29 + .../queries/study/exemptions/.qview.xml | 14 + nbri_ehr/resources/queries/study/flags.js | 6 + .../resources/queries/study/flags.query.xml | 46 + .../resources/queries/study/flags/.qview.xml | 19 + .../resources/queries/study/grossPathology.js | 6 + .../queries/study/grossPathology.query.xml | 41 + .../queries/study/grossPathology/.qview.xml | 12 + .../queries/study/histopathology.query.xml | 16 + .../queries/study/historicalOther.query.xml | 13 + nbri_ehr/resources/queries/study/housing.js | 150 ++ .../resources/queries/study/housing.query.xml | 52 + .../queries/study/housing/.qview.xml | 15 + .../study/housing/Active Housing.qview.xml | 24 + nbri_ehr/resources/queries/study/necropsy.js | 59 + .../queries/study/necropsy.query.xml | 43 + .../queries/study/necropsy/.qview.xml | 18 + .../queries/study/necropsyStatus.sql | 10 + .../resources/queries/study/nhpTraining.js | 6 + .../queries/study/nhpTraining.query.xml | 46 + nbri_ehr/resources/queries/study/notes.js | 6 + .../resources/queries/study/notes.query.xml | 34 + .../resources/queries/study/notes/.qview.xml | 16 + .../study/notificationAnimalProject.sql | 13 + .../queries/study/observationOrdersByDate.sql | 59 + .../study/observationSchedule.query.xml | 20 + .../queries/study/observationSchedule.sql | 49 + .../study/observationSchedule/.qview.xml | 17 + .../queries/study/observation_order.js | 6 + .../queries/study/observation_order.query.xml | 45 + .../study/observation_order/.qview.xml | 20 + .../Active Behavior Orders.qview.xml | 24 + .../Active Clinical Orders.qview.xml | 24 + .../Behavior Orders.qview.xml | 23 + .../Clinical Orders.qview.xml | 23 + .../queries/study/pairingSummary.query.xml | 24 + .../queries/study/pairingSummary.sql | 25 + .../queries/study/pairingSummary/.qview.xml | 27 + .../pairingSummary/Active Pairing.qview.xml | 29 + .../pairingSummary/Pairing History.qview.xml | 25 + nbri_ehr/resources/queries/study/pairings.js | 15 + .../queries/study/pairings.query.xml | 90 + .../queries/study/pairings/.qview.xml | 25 + .../queries/study/parentageSummary.query.xml | 25 + .../queries/study/parentageSummary.sql | 36 + .../queries/study/physicalExam/.qview.xml | 16 + nbri_ehr/resources/queries/study/prc.js | 32 + .../resources/queries/study/prc.query.xml | 73 + .../resources/queries/study/prc/.qview.xml | 14 + .../queries/study/prcOverdue.query.xml | 154 ++ .../resources/queries/study/prcOverdue.sql | 20 + .../queries/study/prcOverdue/.qview.xml | 26 + .../queries/study/prcOverdueNotification.sql | 18 + .../study/prcOverdueNotification/.qview.xml | 5 + .../queries/study/prcSchedule.query.xml | 154 ++ .../resources/queries/study/prcSchedule.sql | 20 + .../queries/study/prcSchedule/.qview.xml | 23 + nbri_ehr/resources/queries/study/prc_order.js | 14 + .../queries/study/prc_order.query.xml | 84 + .../queries/study/prc_order/.qview.xml | 17 + .../queries/study/prc_order_report.query.xml | 84 + .../queries/study/prc_order_report.sql | 6 + .../queries/study/prc_order_report/.qview.xml | 17 + nbri_ehr/resources/queries/study/pregnancy.js | 20 + .../queries/study/pregnancy.query.xml | 28 + .../queries/study/protocolAssignment.js | 128 ++ .../study/protocolAssignment.query.xml | 30 + .../Active Assignments.qview.xml | 8 + .../resources/queries/study/recentCases.sql | 11 + .../queries/study/serology.query.xml | 25 + .../queries/study/serology/.qview.xml | 11 + .../queries/study/tissueDisposition.js | 6 + .../queries/study/tissueDisposition.query.xml | 40 + .../study/tissueDisposition/.qview.xml | 12 + .../queries/study/treatmentSchedule.query.xml | 187 ++ .../queries/study/treatmentSchedule.sql | 79 + .../study/treatmentSchedule/.qview.xml | 28 + .../Clinical Medications.qview.xml | 8 + .../queries/study/treatment_order.js | 23 + .../queries/study/treatment_order.query.xml | 170 ++ .../queries/study/treatment_order/.qview.xml | 31 + ...Behavior Active Treatment Orders.qview.xml | 6 + ...Clinical Active Treatment Orders.qview.xml | 6 + nbri_ehr/resources/queries/study/vitals.js | 7 + .../resources/queries/study/vitals.query.xml | 33 + .../resources/queries/study/vitals/.qview.xml | 19 + .../resources/queries/study/weight.query.xml | 36 + .../resources/queries/study/weight/.qview.xml | 14 + .../.labkey/protocols/kinship/default.xml | 3 + nbri_ehr/resources/referenceStudy/folder.xml | 4 + .../PrimateElectronicHealthRecord.dataset | 19 + .../study/datasets/datasets_manifest.xml | 44 + .../study/datasets/datasets_metadata.xml | 1514 +++++++++++++++ .../resources/referenceStudy/study/study.xml | 7 + .../resources/reports/additionalReports.tsv | 52 + .../postgresql/nbri_ehr-0.000-25.001.sql | 596 ++++++ nbri_ehr/resources/schemas/nbri_ehr.xml | 572 ++++++ nbri_ehr/resources/scripts/nbri_triggers.js | 150 ++ .../views/NBRI_amimalHistory.webpart.xml | 3 + .../resources/views/acquisitionReport.html | 217 +++ .../views/acquisitionReport.view.xml | 6 + nbri_ehr/resources/views/animalHistory.html | 107 ++ .../resources/views/animalHistory.view.xml | 13 + nbri_ehr/resources/views/begin.html | 251 +++ nbri_ehr/resources/views/begin.view.xml | 5 + nbri_ehr/resources/views/begin.webpart.xml | 7 + nbri_ehr/resources/views/cageDetails.html | 83 + nbri_ehr/resources/views/cageDetails.view.xml | 5 + .../views/clinicalHistoryExport.html | 86 + .../views/clinicalHistoryExport.view.xml | 5 + nbri_ehr/resources/views/datasets.html | 130 ++ nbri_ehr/resources/views/datasets.view.xml | 5 + nbri_ehr/resources/views/enterData.html | 43 + nbri_ehr/resources/views/enterData.view.xml | 9 + nbri_ehr/resources/views/nbri_login.html | 48 + nbri_ehr/resources/views/nbri_login.view.xml | 6 + nbri_ehr/resources/views/necropsy.html | 98 + nbri_ehr/resources/views/necropsy.view.xml | 3 + nbri_ehr/resources/views/participantView.html | 31 + .../resources/views/participantView.view.xml | 15 + .../resources/web/ehr/metadata/Default.js | 21 + .../buttons/ProcedureOrderCompleteButton.js | 112 ++ .../nbri_ehr/buttons/RecordProcedureButton.js | 149 ++ .../nbri_ehr/buttons/RecordTreatmentButton.js | 165 ++ .../web/nbri_ehr/buttons/SelectCaseButton.js | 95 + .../nbri_ehr/buttons/addClinicalObsButton.js | 85 + .../nbri_ehr/buttons/clinicalObsGridButton.js | 59 + .../nbri_ehr/buttons/deathNecropsyButtons.js | 144 ++ .../nbri_ehr/buttons/necropsyGridButtons.js | 37 + .../web/nbri_ehr/buttons/saveDraftButton.js | 20 + .../web/nbri_ehr/buttons/treatmentSubmit.js | 273 +++ .../data/AssignmentsAnyIdClientStore.js | 16 + .../nbri_ehr/data/AssignmentsClientStore.js | 60 + .../web/nbri_ehr/data/CaseClientStore.js | 47 + .../web/nbri_ehr/data/CaseStoreCollection.js | 240 +++ .../data/ClinicalObservationClientStore.js | 24 + .../DrugAdministrationRunsChildClientStore.js | 33 + .../data/DrugAdministrationRunsClientStore.js | 59 + .../nbri_ehr/data/ObsOrderChildClientStore.js | 33 + .../web/nbri_ehr/data/ObsOrdersClientStore.js | 45 + .../web/nbri_ehr/field/AnimalIdCases.js | 71 + .../web/nbri_ehr/field/DrugVolumeField.js | 61 + .../resources/web/nbri_ehr/field/EditCase.js | 115 ++ .../web/nbri_ehr/field/LocationField.js | 42 + .../web/nbri_ehr/model/sources/Alias.js | 26 + .../web/nbri_ehr/model/sources/Arrival.js | 113 ++ .../web/nbri_ehr/model/sources/Assignment.js | 49 + .../model/sources/BehaviorDefaults.js | 107 ++ .../nbri_ehr/model/sources/BehaviorRounds.js | 131 ++ .../nbri_ehr/model/sources/BehavioralCase.js | 110 ++ .../web/nbri_ehr/model/sources/Birth.js | 77 + .../nbri_ehr/model/sources/BulkBehavior.js | 75 + .../nbri_ehr/model/sources/BulkClinical.js | 47 + .../nbri_ehr/model/sources/ClinicalCase.js | 158 ++ .../model/sources/ClinicalDefaults.js | 213 +++ .../nbri_ehr/model/sources/ClinicalRounds.js | 131 ++ .../nbri_ehr/model/sources/DeathNecropsy.js | 163 ++ .../model/sources/MedicationEndDate.js | 53 + .../web/nbri_ehr/model/sources/NBRIDefault.js | 353 ++++ .../web/nbri_ehr/model/sources/ObsDefaults.js | 25 + .../web/nbri_ehr/model/sources/ParentChild.js | 25 + .../web/nbri_ehr/model/sources/Pregnancy.js | 31 + .../web/nbri_ehr/model/sources/Rearrival.js | 62 + .../model/sources/TreatmentSchedule.js | 72 + nbri_ehr/resources/web/nbri_ehr/nbri.css | 7 + .../resources/web/nbri_ehr/nbriOverrides.js | 16 + .../resources/web/nbri_ehr/nbriReports.js | 287 +++ .../web/nbri_ehr/nbri_ehr_api.lib.xml | 9 + .../web/nbri_ehr/panel/AnimalDetailsPanel.js | 248 +++ .../panel/ArrivalInstructionsPanel.js | 22 + .../nbri_ehr/panel/BirthInstructionsPanel.js | 21 + .../web/nbri_ehr/panel/BloodSummaryPanel.js | 79 + .../web/nbri_ehr/panel/CaseHistoryPanel.js | 24 + .../web/nbri_ehr/panel/CaseTemplatePanel.js | 58 + .../nbri_ehr/panel/ClinicalHistoryPanel.js | 149 ++ .../web/nbri_ehr/panel/InstructionsPanel.js | 28 + .../panel/NBRIExamCasesDataEntryPanel.js | 44 + .../web/nbri_ehr/panel/NarrowSnapshotPanel.js | 42 + .../web/nbri_ehr/panel/SelectCasePanel.js | 188 ++ .../web/nbri_ehr/panel/SnapshotPanel.js | 394 ++++ .../web/nbri_ehr/plugin/RowEditor.js | 66 + nbri_ehr/resources/web/nbri_ehr/utils.js | 74 + .../web/nbri_ehr/window/AddAnimalsWindow.js | 112 ++ .../nbri_ehr/window/CopyFromSectionWindow.js | 181 ++ .../web/nbri_ehr/window/DrugAmountWindow.js | 326 ++++ .../web/nbri_ehr/window/FormBulkAddWindow.js | 24 + .../window/MarkTreatmentCompletedWindow.js | 188 ++ .../nbri_ehr/window/NBRICaseHistoryWindow.js | 53 + .../window/NBRIClinicalHistoryWindow.js | 74 + .../nbri_ehr/window/NBRIRecentCasesWindow.js | 108 ++ .../window/NBRIRecentRemarksWindow.js | 122 ++ .../web/nbri_ehr/window/SelectCaseWindow.js | 45 + .../labkey/nbri_ehr/NBRI_EHRController.java | 30 + .../org/labkey/nbri_ehr/NBRI_EHRManager.java | 29 + .../org/labkey/nbri_ehr/NBRI_EHRModule.java | 265 +++ .../org/labkey/nbri_ehr/NBRI_EHRSchema.java | 46 + .../buttons/MarkTreatmentCompletedButton.java | 56 + .../dataentry/form/NBRIAliasFormType.java | 49 + .../form/NBRIAnimalTrainingFormType.java | 39 + .../dataentry/form/NBRIArrivalFormType.java | 54 + .../form/NBRIAssignmentFormType.java | 50 + .../dataentry/form/NBRIBaseTaskFormType.java | 56 + .../form/NBRIBehaviorRoundsFormType.java | 119 ++ .../form/NBRIBehavioralCasesFormType.java | 123 ++ .../dataentry/form/NBRIBirthFormType.java | 75 + .../dataentry/form/NBRIBuildingFormType.java | 48 + .../form/NBRIBulkBehaviorFormType.java | 81 + .../form/NBRIBulkClinicalFormType.java | 93 + .../dataentry/form/NBRICageFormType.java | 48 + .../dataentry/form/NBRICasesFormType.java | 150 ++ .../form/NBRIChemistryImportFormType.java | 47 + .../NBRIClinicalObservationsFormType.java | 81 + .../form/NBRIClinicalRoundsFormType.java | 127 ++ .../form/NBRIDeathNecropsyFormType.java | 104 ++ .../dataentry/form/NBRIDepartureFormType.java | 39 + .../form/NBRIExemptionsFormType.java | 41 + .../dataentry/form/NBRIFlagsFormType.java | 41 + .../dataentry/form/NBRIFloorFormType.java | 48 + .../dataentry/form/NBRIHousingFormType.java | 48 + .../form/NBRIMedicationTreatmentFormType.java | 70 + .../dataentry/form/NBRINotesFormType.java | 41 + .../dataentry/form/NBRIPairingsFormType.java | 49 + .../dataentry/form/NBRIPregnancyFormType.java | 48 + .../dataentry/form/NBRIProjectFormType.java | 48 + .../dataentry/form/NBRIProtocolFormType.java | 48 + .../dataentry/form/NBRIRearrivalFormType.java | 58 + .../dataentry/form/NBRIRoomFormType.java | 48 + .../form/NBRISerologyImportFormType.java | 47 + .../dataentry/form/NBRIWeightFormType.java | 39 + .../dataentry/section/BaseFormSection.java | 139 ++ .../section/NBRIAliasFormSection.java | 24 + .../section/NBRIAnimalDetailsFormSection.java | 31 + .../section/NBRIArrivalFormSection.java | 54 + .../NBRIArrivalInstructionsFormSection.java | 41 + .../section/NBRIBirthFormSection.java | 82 + .../NBRIBirthInstructionsFormSection.java | 41 + .../section/NBRIBloodDrawFormSection.java | 95 + .../section/NBRICaseTemplateFormSection.java | 42 + .../section/NBRICasesFormPanelSection.java | 83 + .../NBRIClinicalObservationsFormSection.java | 71 + .../NBRIClinicalRemarksFormPanelSection.java | 89 + .../NBRIClinicalRemarksFormSection.java | 62 + .../section/NBRIDeathFormSection.java | 39 + .../section/NBRIDepartureFormSection.java | 24 + .../section/NBRIExemptionsFormSection.java | 24 + .../section/NBRIFlagsFormSection.java | 24 + .../NBRIGrossPathologyFormSection.java | 56 + .../section/NBRIHousingFormSection.java | 40 + .../section/NBRINecropsyFormSection.java | 51 + .../section/NBRINotesFormSection.java | 24 + .../NBRIObservationOrdersFormSection.java | 70 + .../section/NBRIPregnancyFormSection.java | 24 + .../section/NBRIProcedureFormSection.java | 42 + .../NBRIProcedureOrderFormSection.java | 56 + .../NBRIProjectAssignmentFormSection.java | 37 + .../NBRIProtocolAssignmentFormSection.java | 37 + .../section/NBRIRearrivalFormSection.java | 35 + .../section/NBRITaskFormSection.java | 33 + .../NBRITissueDispositionFormSection.java | 56 + .../NBRITreatmentGivenFormSection.java | 59 + .../NBRITreatmentOrderFormSection.java | 59 + .../section/NBRIVitalsFormSection.java | 42 + .../section/NBRIWeightFormSection.java | 40 + ...ActiveAssignmentsDemographicsProvider.java | 72 + .../ActiveCasesDemographicsProvider.java | 82 + .../ActiveFlagsDemographicsProvider.java | 79 + .../ActiveTreatmentsDemographicsProvider.java | 86 + .../CagematesDemographicsProvider.java | 105 ++ .../HousingDemographicsProvider.java | 58 + .../NecropsyStatusDemographicsProvider.java | 71 + ...rotocolAssignmentDemographicsProvider.java | 70 + .../nbri_ehr/history/ArrivalDataSource.java | 51 + .../nbri_ehr/history/BiopsyDataSource.java | 72 + .../nbri_ehr/history/BirthDataSource.java | 46 + .../nbri_ehr/history/BloodDrawDataSource.java | 51 + .../nbri_ehr/history/BreederDataSource.java | 42 + .../nbri_ehr/history/DeathDataSource.java | 61 + .../nbri_ehr/history/DepartureDataSource.java | 53 + .../nbri_ehr/history/DrugAdminDataSource.java | 82 + .../history/ExemptionsDataSource.java | 66 + .../nbri_ehr/history/FlagsDataSource.java | 66 + .../nbri_ehr/history/FosteringDataSource.java | 49 + .../history/HistopathologyDataSource.java | 49 + .../NBRIBehaviorObservationsDataSource.java | 27 + .../history/NBRICaseCloseDataSource.java | 74 + .../history/NBRICaseOpenDataSource.java | 74 + .../NBRIClinicalObservationsDataSource.java | 26 + .../NBRIClinicalRemarksDataSource.java | 96 + .../NBRIEndTreatmentOrderDataSource.java | 90 + .../history/NBRIHousingDataSource.java | 66 + .../NBRIObservationOrdersDataSource.java | 185 ++ .../history/NBRIObservationsDataSource.java | 198 ++ .../NBRIProcedureOrdersDataSource.java | 72 + .../history/NBRIVitalsDataSource.java | 87 + .../nbri_ehr/history/PairingsDataSource.java | 60 + .../history/PhysicalExamDataSource.java | 69 + .../nbri_ehr/history/PregnancyDataSource.java | 66 + .../history/ProceduresDataSource.java | 68 + .../history/ProjectAssignmentDataSource.java | 30 + .../nbri_ehr/history/ProtocolDataSource.java | 68 + .../nbri_ehr/history/SerologyDataSource.java | 67 + .../NBRIClinicalMoveNotification.java | 67 + .../notification/NBRIDeathNotification.java | 66 + .../NBRIPregnancyOutcomeNotification.java | 66 + .../NBRIProcedureOverdueNotification.java | 275 +++ .../notification/NotificationHelper.java | 75 + .../TriggerScriptNotification.java | 83 + .../nbri_ehr/query/NBRI_EHRTriggerHelper.java | 1150 ++++++++++++ .../nbri_ehr/query/NBRI_EHRUserSchema.java | 43 + .../security/NBRIEHRVetTechPermission.java | 26 + .../nbri_ehr/security/NBRIEHRVetTechRole.java | 36 + .../nbri_ehr/table/NBRI_EHRCustomizer.java | 1441 +++++++++++++++ .../table/NBRI_EHRSharedDatasetTrigger.java | 66 + .../table/NBRI_EHRTriggerScriptFactory.java | 36 + .../test/sampledata/nbriEHRStudyPolicy.xml | 188 ++ .../test/sampledata/nbri_ehr/study/folder.xml | 4 + .../PrimateElectronicHealthRecord.dataset | 19 + .../study/study/datasets/datasetArrival.tsv | 6 + .../study/datasets/datasetAssignment.tsv | 9 + .../study/study/datasets/datasetBirth.tsv | 9 + .../study/study/datasets/datasetDeaths.tsv | 3 + .../study/datasets/datasetDemographics.tsv | 14 + .../study/study/datasets/datasetDeparture.tsv | 5 + .../study/study/datasets/datasetFlags.tsv | 11 + .../study/study/datasets/datasetHousing.tsv | 9 + .../datasets/datasetProtocolAssignment.tsv | 9 + .../study/study/datasets/datasetWeight.tsv | 811 +++++++++ .../sampledata/nbri_ehr/study/study/study.xml | 6 + .../tests.nbri_ehr/NBRI_EHRTest.java | 1617 +++++++++++++++++ 650 files changed, 36037 insertions(+), 6 deletions(-) create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 nbri_ehr/build.gradle create mode 100644 nbri_ehr/module.properties create mode 100644 nbri_ehr/resources/data/abdominal_obs_types.tsv create mode 100644 nbri_ehr/resources/data/abnormal_behavior_types.tsv create mode 100644 nbri_ehr/resources/data/acquisition_type.tsv create mode 100644 nbri_ehr/resources/data/activity.tsv create mode 100644 nbri_ehr/resources/data/ageclass.tsv create mode 100644 nbri_ehr/resources/data/alias_category.tsv create mode 100644 nbri_ehr/resources/data/alopecia_regrowth.tsv create mode 100644 nbri_ehr/resources/data/alopecia_score.tsv create mode 100644 nbri_ehr/resources/data/alopecia_type.tsv create mode 100644 nbri_ehr/resources/data/amount_units.tsv create mode 100644 nbri_ehr/resources/data/app_score.tsv create mode 100644 nbri_ehr/resources/data/arrival_type.tsv create mode 100644 nbri_ehr/resources/data/att_score.tsv create mode 100644 nbri_ehr/resources/data/bandage_observations.tsv create mode 100644 nbri_ehr/resources/data/bcs_score.tsv create mode 100644 nbri_ehr/resources/data/behavior_abnormality.tsv create mode 100644 nbri_ehr/resources/data/behavior_mgmt_codes.tsv create mode 100644 nbri_ehr/resources/data/behavior_types.tsv create mode 100644 nbri_ehr/resources/data/blood_draw_reason.tsv create mode 100644 nbri_ehr/resources/data/blood_draw_tube_type.tsv create mode 100644 nbri_ehr/resources/data/blood_sample_type.tsv create mode 100644 nbri_ehr/resources/data/blood_tube_volumes.tsv create mode 100644 nbri_ehr/resources/data/cage_type.tsv create mode 100644 nbri_ehr/resources/data/calculated_status_codes.tsv create mode 100644 nbri_ehr/resources/data/capillary_refill_time.tsv create mode 100644 nbri_ehr/resources/data/card_format.tsv create mode 100644 nbri_ehr/resources/data/census_activity_status.tsv create mode 100644 nbri_ehr/resources/data/conc_units.tsv create mode 100644 nbri_ehr/resources/data/cost_type.tsv create mode 100644 nbri_ehr/resources/data/country.tsv create mode 100644 nbri_ehr/resources/data/country_category.tsv create mode 100644 nbri_ehr/resources/data/daily_enrich_codes.tsv create mode 100644 nbri_ehr/resources/data/data_category.tsv create mode 100644 nbri_ehr/resources/data/death_reason.tsv create mode 100644 nbri_ehr/resources/data/delivery_state.tsv create mode 100644 nbri_ehr/resources/data/dental_obs.tsv create mode 100644 nbri_ehr/resources/data/derm_obs.tsv create mode 100644 nbri_ehr/resources/data/divider_types.tsv create mode 100644 nbri_ehr/resources/data/dosage_units.tsv create mode 100644 nbri_ehr/resources/data/editable_lookups.tsv create mode 100644 nbri_ehr/resources/data/esig_events.tsv create mode 100644 nbri_ehr/resources/data/euthanasia_type.tsv create mode 100644 nbri_ehr/resources/data/exam_findings.tsv create mode 100644 nbri_ehr/resources/data/exemption_category.tsv create mode 100644 nbri_ehr/resources/data/expense_class.tsv create mode 100644 nbri_ehr/resources/data/fecal_smear_score.tsv create mode 100644 nbri_ehr/resources/data/feed_assess_types.tsv create mode 100644 nbri_ehr/resources/data/gender_codes.tsv create mode 100644 nbri_ehr/resources/data/general_obs.tsv create mode 100644 nbri_ehr/resources/data/genitourinary_obs.tsv create mode 100644 nbri_ehr/resources/data/geographic_origins.tsv create mode 100644 nbri_ehr/resources/data/hernia_types.tsv create mode 100644 nbri_ehr/resources/data/housing_reason.tsv create mode 100644 nbri_ehr/resources/data/hyd_score.tsv create mode 100644 nbri_ehr/resources/data/id_history_type.tsv create mode 100644 nbri_ehr/resources/data/incision_score.tsv create mode 100644 nbri_ehr/resources/data/indoor_outdoor.tsv create mode 100644 nbri_ehr/resources/data/lameness.tsv create mode 100644 nbri_ehr/resources/data/lookup_sets.tsv create mode 100644 nbri_ehr/resources/data/lookupsManifest.tsv create mode 100644 nbri_ehr/resources/data/lookupsManifestTest.tsv create mode 100644 nbri_ehr/resources/data/mens_score.tsv create mode 100644 nbri_ehr/resources/data/mucous_membranes.tsv create mode 100644 nbri_ehr/resources/data/musculoskeletal_observations.tsv create mode 100644 nbri_ehr/resources/data/necropsy_disposition_codes.tsv create mode 100644 nbri_ehr/resources/data/necropsy_exam_reason.tsv create mode 100644 nbri_ehr/resources/data/necropsy_organ_appearance.tsv create mode 100644 nbri_ehr/resources/data/necropsy_organ_systems.tsv create mode 100644 nbri_ehr/resources/data/necropsy_physical_condition.tsv create mode 100644 nbri_ehr/resources/data/necropsy_specimen_condition.tsv create mode 100644 nbri_ehr/resources/data/necropsy_tissue.tsv create mode 100644 nbri_ehr/resources/data/neurologic_observations.tsv create mode 100644 nbri_ehr/resources/data/nhp_training_reason.tsv create mode 100644 nbri_ehr/resources/data/nhp_training_result.tsv create mode 100644 nbri_ehr/resources/data/nhp_training_type.tsv create mode 100644 nbri_ehr/resources/data/normal_abnormal.tsv create mode 100644 nbri_ehr/resources/data/normal_abnormal_only.tsv create mode 100644 nbri_ehr/resources/data/numeric_unit.tsv create mode 100644 nbri_ehr/resources/data/observation_areas.tsv create mode 100644 nbri_ehr/resources/data/observation_types.tsv create mode 100644 nbri_ehr/resources/data/obstetric_observations.tsv create mode 100644 nbri_ehr/resources/data/ocular_observations.tsv create mode 100644 nbri_ehr/resources/data/pairing_formation_types.tsv create mode 100644 nbri_ehr/resources/data/pairing_goal.tsv create mode 100644 nbri_ehr/resources/data/pairing_observation.tsv create mode 100644 nbri_ehr/resources/data/pairing_reason.tsv create mode 100644 nbri_ehr/resources/data/pairing_separation_reason.tsv create mode 100644 nbri_ehr/resources/data/preferences.tsv create mode 100644 nbri_ehr/resources/data/pregnancy_result.tsv create mode 100644 nbri_ehr/resources/data/problem_list_category.tsv create mode 100644 nbri_ehr/resources/data/problem_list_subcategory.tsv create mode 100644 nbri_ehr/resources/data/procedure_category.tsv create mode 100644 nbri_ehr/resources/data/procedures.tsv create mode 100644 nbri_ehr/resources/data/protocol_category.tsv create mode 100644 nbri_ehr/resources/data/protocol_state.tsv create mode 100644 nbri_ehr/resources/data/protocol_type.tsv create mode 100644 nbri_ehr/resources/data/qualifier.tsv create mode 100644 nbri_ehr/resources/data/questionnaire.tsv create mode 100644 nbri_ehr/resources/data/rectal_prolapse.tsv create mode 100644 nbri_ehr/resources/data/regulatory_stress_levels.tsv create mode 100644 nbri_ehr/resources/data/req_order_state.tsv create mode 100644 nbri_ehr/resources/data/req_order_type.tsv create mode 100644 nbri_ehr/resources/data/respiratory_observations.tsv create mode 100644 nbri_ehr/resources/data/routes.tsv create mode 100644 nbri_ehr/resources/data/sib_score.tsv create mode 100644 nbri_ehr/resources/data/snomed.tsv create mode 100644 nbri_ehr/resources/data/source.tsv create mode 100644 nbri_ehr/resources/data/species.tsv create mode 100644 nbri_ehr/resources/data/species_codes.tsv create mode 100644 nbri_ehr/resources/data/stool_score.tsv create mode 100644 nbri_ehr/resources/data/stool_types.tsv create mode 100644 nbri_ehr/resources/data/temperament.tsv create mode 100644 nbri_ehr/resources/data/testicular_volume.tsv create mode 100644 nbri_ehr/resources/data/treatment_frequency.tsv create mode 100644 nbri_ehr/resources/data/treatment_frequency_times.tsv create mode 100644 nbri_ehr/resources/data/vaginal_uterine_prolapse.tsv create mode 100644 nbri_ehr/resources/data/vendor_approval_code.tsv create mode 100644 nbri_ehr/resources/data/vendor_production_location.tsv create mode 100644 nbri_ehr/resources/data/volume_units.tsv create mode 100644 nbri_ehr/resources/data/weight_ranges.tsv create mode 100644 nbri_ehr/resources/data/wound_severity.tsv create mode 100644 nbri_ehr/resources/data/wound_status_behavior.tsv create mode 100644 nbri_ehr/resources/data/wound_status_clinical.tsv create mode 100644 nbri_ehr/resources/data/yes_no_only.tsv create mode 100644 nbri_ehr/resources/data/yes_no_order.tsv create mode 100644 nbri_ehr/resources/domain-templates/ehr.template.xml create mode 100644 nbri_ehr/resources/domain-templates/ehr_lookups.template.xml create mode 100644 nbri_ehr/resources/folderTypes/NBRI_EHR.folderType.xml create mode 100644 nbri_ehr/resources/module.xml create mode 100644 nbri_ehr/resources/queries/ehr/activeProtocols.sql create mode 100644 nbri_ehr/resources/queries/ehr/my_tasks.query.xml create mode 100644 nbri_ehr/resources/queries/ehr/my_tasks.sql create mode 100644 nbri_ehr/resources/queries/ehr/my_tasks/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr/my_tasks/Active Tasks.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr/my_tasks/Review Required.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr/observation_types.query.xml create mode 100644 nbri_ehr/resources/queries/ehr/project.js create mode 100644 nbri_ehr/resources/queries/ehr/project.query.xml create mode 100644 nbri_ehr/resources/queries/ehr/project/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr/protocol.js create mode 100644 nbri_ehr/resources/queries/ehr/protocol.query.xml create mode 100644 nbri_ehr/resources/queries/ehr/protocol/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr/protocolActiveAnimals.query.xml create mode 100644 nbri_ehr/resources/queries/ehr/protocolActiveAnimals.sql create mode 100644 nbri_ehr/resources/queries/ehr/protocolAnimals.query.xml create mode 100644 nbri_ehr/resources/queries/ehr/protocolAnimals.sql create mode 100644 nbri_ehr/resources/queries/ehr/protocolHistoricAnimals.sql create mode 100644 nbri_ehr/resources/queries/ehr/protocolTotalAnimalsBySpecies.query.xml create mode 100644 nbri_ehr/resources/queries/ehr/protocolTotalAnimalsBySpecies.sql create mode 100644 nbri_ehr/resources/queries/ehr/protocol_counts.query.xml create mode 100644 nbri_ehr/resources/queries/ehr/protocol_counts/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr/tasks/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr/tasks/Active Tasks.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr/tasks/Review Required.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/ageclass.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/areas/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/buildings.js create mode 100644 nbri_ehr/resources/queries/ehr_lookups/buildings.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/buildings/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/cage.js create mode 100644 nbri_ehr/resources/queries/ehr_lookups/cage.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/cage/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/country.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/floors.js create mode 100644 nbri_ehr/resources/queries/ehr_lookups/floors.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/floors/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/procedures/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/roomUtilization.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/roomUtilization.sql create mode 100644 nbri_ehr/resources/queries/ehr_lookups/roomUtilizationByBuilding.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/roomUtilizationByBuilding.sql create mode 100644 nbri_ehr/resources/queries/ehr_lookups/rooms.js create mode 100644 nbri_ehr/resources/queries/ehr_lookups/rooms.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/rooms/.qview.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/snomed.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/species_codes.query.xml create mode 100644 nbri_ehr/resources/queries/ehr_lookups/vendor_production_location.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/Account.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/AnimalDelivery.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/AnimalDeliveryEsig.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/AnimalReqOrder.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/AnimalReqOrderEsig.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/AnimalShipment.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/AnimalVendor.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/AnimalVendor/.qview.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/CageCard.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/CageCardHistory.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/DeletedRecord.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/Department.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/IdHistory.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/Lot.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/ProtocolEsig.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/ProtocolProcedures.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/ProtocolStress.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/QuestionResponse.js create mode 100644 nbri_ehr/resources/queries/nbri_ehr/QuestionResponse.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/dateRange.sql create mode 100644 nbri_ehr/resources/queries/nbri_ehr/locationTypes/.qview.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/locations.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/locations/.qview.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/locationsMapping.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/locationsMapping/.qview.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/necropsyTasks.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/necropsyTasks.sql create mode 100644 nbri_ehr/resources/queries/nbri_ehr/necropsyTasks/.qview.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/staff.query.xml create mode 100644 nbri_ehr/resources/queries/nbri_ehr/stress.query.xml create mode 100644 nbri_ehr/resources/queries/study/AcquisitionReport.sql create mode 100644 nbri_ehr/resources/queries/study/AcquisitionReportBySpecies.sql create mode 100644 nbri_ehr/resources/queries/study/BehaviorClinRemarks.sql create mode 100644 nbri_ehr/resources/queries/study/BehaviorClinRemarks/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/ClinicalClinRemarks.sql create mode 100644 nbri_ehr/resources/queries/study/ClinicalClinRemarks/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/CurrentProtocolProjectReport.sql create mode 100644 nbri_ehr/resources/queries/study/MHC.js create mode 100644 nbri_ehr/resources/queries/study/MHC.query.xml create mode 100644 nbri_ehr/resources/queries/study/Pedigree.sql create mode 100644 nbri_ehr/resources/queries/study/Weight.js create mode 100644 nbri_ehr/resources/queries/study/activeAssignments.sql create mode 100644 nbri_ehr/resources/queries/study/activeBehaviorCases.sql create mode 100644 nbri_ehr/resources/queries/study/activeBehaviorCases/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/activeClinicalCases.sql create mode 100644 nbri_ehr/resources/queries/study/activeClinicalCases/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/activeProjectsFromHousing.sql create mode 100644 nbri_ehr/resources/queries/study/activeTreatmentOrders.sql create mode 100644 nbri_ehr/resources/queries/study/alias.js create mode 100644 nbri_ehr/resources/queries/study/alias.query.xml create mode 100644 nbri_ehr/resources/queries/study/aliases.sql create mode 100644 nbri_ehr/resources/queries/study/alopecia/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/arrival.js create mode 100644 nbri_ehr/resources/queries/study/arrival.query.xml create mode 100644 nbri_ehr/resources/queries/study/arrival/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/assignment.js create mode 100644 nbri_ehr/resources/queries/study/assignment.query.xml create mode 100644 nbri_ehr/resources/queries/study/behaviorCases.sql create mode 100644 nbri_ehr/resources/queries/study/behaviorCases/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/behaviorObservations.sql create mode 100644 nbri_ehr/resources/queries/study/behaviorObservations/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/birth.js create mode 100644 nbri_ehr/resources/queries/study/birth.query.xml create mode 100644 nbri_ehr/resources/queries/study/blood/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/bloodDrawChanges.sql create mode 100644 nbri_ehr/resources/queries/study/breeder/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/cases.js create mode 100644 nbri_ehr/resources/queries/study/cases.query.xml create mode 100644 nbri_ehr/resources/queries/study/cases/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/cases/Active Behavior Cases.qview.xml create mode 100644 nbri_ehr/resources/queries/study/cases/Active Clinical Cases.qview.xml create mode 100644 nbri_ehr/resources/queries/study/cases/All Behavior Cases.qview.xml create mode 100644 nbri_ehr/resources/queries/study/cases/All Clinical Cases.qview.xml create mode 100644 nbri_ehr/resources/queries/study/chemistryResults.query.xml create mode 100644 nbri_ehr/resources/queries/study/chemistryResults/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinicalCases.sql create mode 100644 nbri_ehr/resources/queries/study/clinicalCases/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinicalObservations.sql create mode 100644 nbri_ehr/resources/queries/study/clinicalObservations/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinical_observations.js create mode 100644 nbri_ehr/resources/queries/study/clinical_observations.query.xml create mode 100644 nbri_ehr/resources/queries/study/clinical_observations/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinical_observations/Alopecia Scores.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinical_observations/Behavior.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinical_observations/Clinical.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinical_observationsSummary.sql create mode 100644 nbri_ehr/resources/queries/study/clinical_observationsSummary/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinremarks.js create mode 100644 nbri_ehr/resources/queries/study/clinremarks.query.xml create mode 100644 nbri_ehr/resources/queries/study/clinremarks/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinremarks/Behavior.qview.xml create mode 100644 nbri_ehr/resources/queries/study/clinremarks/Clinical.qview.xml create mode 100644 nbri_ehr/resources/queries/study/colonyPopulationByAgeClass.query.xml create mode 100644 nbri_ehr/resources/queries/study/colonyPopulationChange.sql create mode 100644 nbri_ehr/resources/queries/study/colonyPopulationSummary.query.xml create mode 100644 nbri_ehr/resources/queries/study/currentBloodDraws.sql create mode 100644 nbri_ehr/resources/queries/study/currentproject.sql create mode 100644 nbri_ehr/resources/queries/study/deathNotification.sql create mode 100644 nbri_ehr/resources/queries/study/deaths.js create mode 100644 nbri_ehr/resources/queries/study/deaths.query.xml create mode 100644 nbri_ehr/resources/queries/study/deaths/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/demographics.js create mode 100644 nbri_ehr/resources/queries/study/demographics.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographics/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsActiveFlags.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsActiveProjectAssignment.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsActiveProtocolAssignment.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsActiveProtocolAssignment.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsAliases.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsAliases.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsCagemates.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsCagemates.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsCurLocation.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsCurLocation.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsLastProject.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsLastProject.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsLastProtocol.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsLastProtocol.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsOffspring.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsOffspring.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsParents.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsParents.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsSiblings.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsSiblings.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsSource.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsSource.sql create mode 100644 nbri_ehr/resources/queries/study/demographicsTotalOffspring.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsTotalOffspring.sql create mode 100644 nbri_ehr/resources/queries/study/departure.js create mode 100644 nbri_ehr/resources/queries/study/departure.query.xml create mode 100644 nbri_ehr/resources/queries/study/departure/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/drug.js create mode 100644 nbri_ehr/resources/queries/study/drug.query.xml create mode 100644 nbri_ehr/resources/queries/study/drug/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/drug/Behavior.qview.xml create mode 100644 nbri_ehr/resources/queries/study/exemptions.js create mode 100644 nbri_ehr/resources/queries/study/exemptions.query.xml create mode 100644 nbri_ehr/resources/queries/study/exemptions/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/flags.js create mode 100644 nbri_ehr/resources/queries/study/flags.query.xml create mode 100644 nbri_ehr/resources/queries/study/flags/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/grossPathology.js create mode 100644 nbri_ehr/resources/queries/study/grossPathology.query.xml create mode 100644 nbri_ehr/resources/queries/study/grossPathology/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/histopathology.query.xml create mode 100644 nbri_ehr/resources/queries/study/historicalOther.query.xml create mode 100644 nbri_ehr/resources/queries/study/housing.js create mode 100644 nbri_ehr/resources/queries/study/housing.query.xml create mode 100644 nbri_ehr/resources/queries/study/housing/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/housing/Active Housing.qview.xml create mode 100644 nbri_ehr/resources/queries/study/necropsy.js create mode 100644 nbri_ehr/resources/queries/study/necropsy.query.xml create mode 100644 nbri_ehr/resources/queries/study/necropsy/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/necropsyStatus.sql create mode 100644 nbri_ehr/resources/queries/study/nhpTraining.js create mode 100644 nbri_ehr/resources/queries/study/nhpTraining.query.xml create mode 100644 nbri_ehr/resources/queries/study/notes.js create mode 100644 nbri_ehr/resources/queries/study/notes.query.xml create mode 100644 nbri_ehr/resources/queries/study/notes/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/notificationAnimalProject.sql create mode 100644 nbri_ehr/resources/queries/study/observationOrdersByDate.sql create mode 100644 nbri_ehr/resources/queries/study/observationSchedule.query.xml create mode 100644 nbri_ehr/resources/queries/study/observationSchedule.sql create mode 100644 nbri_ehr/resources/queries/study/observationSchedule/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/observation_order.js create mode 100644 nbri_ehr/resources/queries/study/observation_order.query.xml create mode 100644 nbri_ehr/resources/queries/study/observation_order/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/observation_order/Active Behavior Orders.qview.xml create mode 100644 nbri_ehr/resources/queries/study/observation_order/Active Clinical Orders.qview.xml create mode 100644 nbri_ehr/resources/queries/study/observation_order/Behavior Orders.qview.xml create mode 100644 nbri_ehr/resources/queries/study/observation_order/Clinical Orders.qview.xml create mode 100644 nbri_ehr/resources/queries/study/pairingSummary.query.xml create mode 100644 nbri_ehr/resources/queries/study/pairingSummary.sql create mode 100644 nbri_ehr/resources/queries/study/pairingSummary/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/pairingSummary/Active Pairing.qview.xml create mode 100644 nbri_ehr/resources/queries/study/pairingSummary/Pairing History.qview.xml create mode 100644 nbri_ehr/resources/queries/study/pairings.js create mode 100644 nbri_ehr/resources/queries/study/pairings.query.xml create mode 100644 nbri_ehr/resources/queries/study/pairings/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/parentageSummary.query.xml create mode 100644 nbri_ehr/resources/queries/study/parentageSummary.sql create mode 100644 nbri_ehr/resources/queries/study/physicalExam/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/prc.js create mode 100644 nbri_ehr/resources/queries/study/prc.query.xml create mode 100644 nbri_ehr/resources/queries/study/prc/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/prcOverdue.query.xml create mode 100644 nbri_ehr/resources/queries/study/prcOverdue.sql create mode 100644 nbri_ehr/resources/queries/study/prcOverdue/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/prcOverdueNotification.sql create mode 100644 nbri_ehr/resources/queries/study/prcOverdueNotification/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/prcSchedule.query.xml create mode 100644 nbri_ehr/resources/queries/study/prcSchedule.sql create mode 100644 nbri_ehr/resources/queries/study/prcSchedule/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/prc_order.js create mode 100644 nbri_ehr/resources/queries/study/prc_order.query.xml create mode 100644 nbri_ehr/resources/queries/study/prc_order/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/prc_order_report.query.xml create mode 100644 nbri_ehr/resources/queries/study/prc_order_report.sql create mode 100644 nbri_ehr/resources/queries/study/prc_order_report/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/pregnancy.js create mode 100644 nbri_ehr/resources/queries/study/pregnancy.query.xml create mode 100644 nbri_ehr/resources/queries/study/protocolAssignment.js create mode 100644 nbri_ehr/resources/queries/study/protocolAssignment.query.xml create mode 100644 nbri_ehr/resources/queries/study/protocolAssignment/Active Assignments.qview.xml create mode 100644 nbri_ehr/resources/queries/study/recentCases.sql create mode 100644 nbri_ehr/resources/queries/study/serology.query.xml create mode 100644 nbri_ehr/resources/queries/study/serology/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/tissueDisposition.js create mode 100644 nbri_ehr/resources/queries/study/tissueDisposition.query.xml create mode 100644 nbri_ehr/resources/queries/study/tissueDisposition/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/treatmentSchedule.query.xml create mode 100644 nbri_ehr/resources/queries/study/treatmentSchedule.sql create mode 100644 nbri_ehr/resources/queries/study/treatmentSchedule/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/treatmentSchedule/Clinical Medications.qview.xml create mode 100644 nbri_ehr/resources/queries/study/treatment_order.js create mode 100644 nbri_ehr/resources/queries/study/treatment_order.query.xml create mode 100644 nbri_ehr/resources/queries/study/treatment_order/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/treatment_order/Behavior Active Treatment Orders.qview.xml create mode 100644 nbri_ehr/resources/queries/study/treatment_order/Clinical Active Treatment Orders.qview.xml create mode 100644 nbri_ehr/resources/queries/study/vitals.js create mode 100644 nbri_ehr/resources/queries/study/vitals.query.xml create mode 100644 nbri_ehr/resources/queries/study/vitals/.qview.xml create mode 100644 nbri_ehr/resources/queries/study/weight.query.xml create mode 100644 nbri_ehr/resources/queries/study/weight/.qview.xml create mode 100644 nbri_ehr/resources/referenceStudy/.labkey/protocols/kinship/default.xml create mode 100644 nbri_ehr/resources/referenceStudy/folder.xml create mode 100644 nbri_ehr/resources/referenceStudy/study/datasets/PrimateElectronicHealthRecord.dataset create mode 100644 nbri_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml create mode 100644 nbri_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml create mode 100644 nbri_ehr/resources/referenceStudy/study/study.xml create mode 100644 nbri_ehr/resources/reports/additionalReports.tsv create mode 100644 nbri_ehr/resources/schemas/dbscripts/postgresql/nbri_ehr-0.000-25.001.sql create mode 100644 nbri_ehr/resources/schemas/nbri_ehr.xml create mode 100644 nbri_ehr/resources/scripts/nbri_triggers.js create mode 100644 nbri_ehr/resources/views/NBRI_amimalHistory.webpart.xml create mode 100644 nbri_ehr/resources/views/acquisitionReport.html create mode 100644 nbri_ehr/resources/views/acquisitionReport.view.xml create mode 100644 nbri_ehr/resources/views/animalHistory.html create mode 100644 nbri_ehr/resources/views/animalHistory.view.xml create mode 100644 nbri_ehr/resources/views/begin.html create mode 100644 nbri_ehr/resources/views/begin.view.xml create mode 100644 nbri_ehr/resources/views/begin.webpart.xml create mode 100644 nbri_ehr/resources/views/cageDetails.html create mode 100644 nbri_ehr/resources/views/cageDetails.view.xml create mode 100644 nbri_ehr/resources/views/clinicalHistoryExport.html create mode 100644 nbri_ehr/resources/views/clinicalHistoryExport.view.xml create mode 100644 nbri_ehr/resources/views/datasets.html create mode 100644 nbri_ehr/resources/views/datasets.view.xml create mode 100644 nbri_ehr/resources/views/enterData.html create mode 100644 nbri_ehr/resources/views/enterData.view.xml create mode 100644 nbri_ehr/resources/views/nbri_login.html create mode 100644 nbri_ehr/resources/views/nbri_login.view.xml create mode 100644 nbri_ehr/resources/views/necropsy.html create mode 100644 nbri_ehr/resources/views/necropsy.view.xml create mode 100644 nbri_ehr/resources/views/participantView.html create mode 100644 nbri_ehr/resources/views/participantView.view.xml create mode 100644 nbri_ehr/resources/web/ehr/metadata/Default.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/ProcedureOrderCompleteButton.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/RecordProcedureButton.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/RecordTreatmentButton.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/SelectCaseButton.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/addClinicalObsButton.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/clinicalObsGridButton.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/deathNecropsyButtons.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/necropsyGridButtons.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/saveDraftButton.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/buttons/treatmentSubmit.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/AssignmentsAnyIdClientStore.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/AssignmentsClientStore.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/CaseClientStore.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/CaseStoreCollection.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/ClinicalObservationClientStore.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/DrugAdministrationRunsChildClientStore.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/DrugAdministrationRunsClientStore.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/ObsOrderChildClientStore.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/ObsOrdersClientStore.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/field/AnimalIdCases.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/field/DrugVolumeField.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/field/EditCase.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/field/LocationField.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/Alias.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/Arrival.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/Assignment.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/BehaviorDefaults.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/BehaviorRounds.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/BehavioralCase.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/Birth.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/BulkBehavior.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/BulkClinical.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalCase.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalDefaults.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalRounds.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/DeathNecropsy.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/MedicationEndDate.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/NBRIDefault.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/ObsDefaults.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/ParentChild.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/Pregnancy.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/Rearrival.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/TreatmentSchedule.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/nbri.css create mode 100644 nbri_ehr/resources/web/nbri_ehr/nbriOverrides.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/nbriReports.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/nbri_ehr_api.lib.xml create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/AnimalDetailsPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/ArrivalInstructionsPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/BirthInstructionsPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/BloodSummaryPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/CaseHistoryPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/CaseTemplatePanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/ClinicalHistoryPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/InstructionsPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/NBRIExamCasesDataEntryPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/NarrowSnapshotPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/SelectCasePanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/panel/SnapshotPanel.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/plugin/RowEditor.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/utils.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/AddAnimalsWindow.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/CopyFromSectionWindow.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/DrugAmountWindow.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/FormBulkAddWindow.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/MarkTreatmentCompletedWindow.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/NBRICaseHistoryWindow.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/NBRIClinicalHistoryWindow.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/NBRIRecentCasesWindow.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/NBRIRecentRemarksWindow.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/window/SelectCaseWindow.js create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRController.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRManager.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRModule.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRSchema.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/buttons/MarkTreatmentCompletedButton.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIAliasFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIAnimalTrainingFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIArrivalFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIAssignmentFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIBaseTaskFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIBehaviorRoundsFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIBehavioralCasesFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIBirthFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIBuildingFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIBulkBehaviorFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIBulkClinicalFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRICageFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRICasesFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIChemistryImportFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIClinicalObservationsFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIClinicalRoundsFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIDeathNecropsyFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIDepartureFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIExemptionsFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIFlagsFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIFloorFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIHousingFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIMedicationTreatmentFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRINotesFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIPairingsFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIPregnancyFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIProjectFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIProtocolFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIRearrivalFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIRoomFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRISerologyImportFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIWeightFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/BaseFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIAliasFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIAnimalDetailsFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIArrivalFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIArrivalInstructionsFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIBirthFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIBirthInstructionsFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIBloodDrawFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRICaseTemplateFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRICasesFormPanelSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIClinicalObservationsFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIClinicalRemarksFormPanelSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIClinicalRemarksFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIDeathFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIDepartureFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIExemptionsFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIFlagsFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIGrossPathologyFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIHousingFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRINecropsyFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRINotesFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIObservationOrdersFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIPregnancyFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIProcedureFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIProcedureOrderFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIProjectAssignmentFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIProtocolAssignmentFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIRearrivalFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRITaskFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRITissueDispositionFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRITreatmentGivenFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRITreatmentOrderFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIVitalsFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIWeightFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/demographics/ActiveAssignmentsDemographicsProvider.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/demographics/ActiveCasesDemographicsProvider.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/demographics/ActiveFlagsDemographicsProvider.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/demographics/ActiveTreatmentsDemographicsProvider.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/demographics/CagematesDemographicsProvider.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/demographics/HousingDemographicsProvider.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/demographics/NecropsyStatusDemographicsProvider.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/demographics/ProtocolAssignmentDemographicsProvider.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/ArrivalDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/BiopsyDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/BirthDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/BloodDrawDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/BreederDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/DeathDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/DepartureDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/DrugAdminDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/ExemptionsDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/FlagsDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/FosteringDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/HistopathologyDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRIBehaviorObservationsDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRICaseCloseDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRICaseOpenDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRIClinicalObservationsDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRIClinicalRemarksDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRIEndTreatmentOrderDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRIHousingDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRIObservationOrdersDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRIObservationsDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRIProcedureOrdersDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/NBRIVitalsDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/PairingsDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/PhysicalExamDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/PregnancyDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/ProceduresDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/ProjectAssignmentDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/ProtocolDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/SerologyDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/notification/NBRIClinicalMoveNotification.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/notification/NBRIDeathNotification.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/notification/NBRIPregnancyOutcomeNotification.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/notification/NBRIProcedureOverdueNotification.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/notification/NotificationHelper.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/notification/TriggerScriptNotification.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/query/NBRI_EHRTriggerHelper.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/query/NBRI_EHRUserSchema.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/security/NBRIEHRVetTechPermission.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/security/NBRIEHRVetTechRole.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRCustomizer.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRSharedDatasetTrigger.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRTriggerScriptFactory.java create mode 100644 nbri_ehr/test/sampledata/nbriEHRStudyPolicy.xml create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/folder.xml create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/PrimateElectronicHealthRecord.dataset create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetArrival.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetAssignment.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetBirth.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetDeaths.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetDemographics.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetDeparture.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetFlags.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetHousing.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetProtocolAssignment.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/datasets/datasetWeight.tsv create mode 100644 nbri_ehr/test/sampledata/nbri_ehr/study/study/study.xml create mode 100644 nbri_ehr/test/src/org.labkey.test/tests.nbri_ehr/NBRI_EHRTest.java diff --git a/.github/workflows/branch_release.yml b/.github/workflows/branch_release.yml index c9583b2..18114e6 100644 --- a/.github/workflows/branch_release.yml +++ b/.github/workflows/branch_release.yml @@ -8,6 +8,10 @@ on: tags: - '*' +permissions: + pull-requests: write + contents: write + jobs: branch_release: if: github.event.created && github.event.sender.login == 'labkey-teamcity' @@ -15,9 +19,9 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create branches and PRs uses: LabKey/gitHubActions/branch-release@develop with: - github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/merge_release.yml b/.github/workflows/merge_release.yml index 306d9e0..341828f 100644 --- a/.github/workflows/merge_release.yml +++ b/.github/workflows/merge_release.yml @@ -8,6 +8,10 @@ on: types: - submitted +permissions: + pull-requests: write + contents: write + jobs: merge_release: if: > @@ -17,7 +21,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Merge PR uses: LabKey/gitHubActions/merge-release@develop @@ -25,4 +29,4 @@ jobs: target_branch: ${{ github.event.pull_request.base.ref }} merge_branch: ${{ github.event.pull_request.head.ref }} pr_number: ${{ github.event.pull_request.number }} - github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/validate_pr.yml b/.github/workflows/validate_pr.yml index 0af0396..69320ba 100644 --- a/.github/workflows/validate_pr.yml +++ b/.github/workflows/validate_pr.yml @@ -10,6 +10,9 @@ on: - reopened - ready_for_review +permissions: + pull-requests: write + jobs: validate_pr: if: github.event.pull_request.head.repo.owner.login == 'LabKey' @@ -23,4 +26,4 @@ jobs: pr_head: ${{ github.event.pull_request.head.ref }} pr_number: ${{ github.event.pull_request.number }} pr_title: ${{ github.event.pull_request.title }} - github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 99c4bf4..06e7b02 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,11 @@ .gradle build/ +# Log Files +nbri_ehr/resources/referenceStudy/etlLogs/ +nbri_ehr/resources/referenceStudy/*.log +nbri_ehr/test/sampledata/nbri_ehr/study/*.log + # Ignore Gradle GUI config gradle-app.setting @@ -21,4 +26,4 @@ gradle-app.setting *.ear # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* \ No newline at end of file +hs_err_pid* diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..bd63829 --- /dev/null +++ b/build.gradle @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021-2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import org.labkey.gradle.util.BuildUtils +import org.labkey.gradle.util.ModuleFinder + +subprojects { + Project p -> + if (ModuleFinder.isPotentialModule(p)) + { + p.evaluationDependsOn(BuildUtils.getApiProjectPath(p.gradle)) + apply plugin: 'java' + apply plugin: 'org.labkey.build.module' + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..f486eab --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +moduleContainer=:server:modules:nbriEHRModules \ No newline at end of file diff --git a/nbri_ehr/build.gradle b/nbri_ehr/build.gradle new file mode 100644 index 0000000..e147134 --- /dev/null +++ b/nbri_ehr/build.gradle @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import org.labkey.gradle.util.BuildUtils + +dependencies + { + BuildUtils.addLabKeyDependency(project: project, config: "implementation", depProjectPath: ":server:modules:ehrModules:ehr", depProjectConfig: "apiJarFile") + BuildUtils.addLabKeyDependency(project: project, config: "implementation", depProjectPath: ":server:modules:LabDevKitModules:LDK", depProjectConfig: "apiJarFile") + BuildUtils.addLabKeyDependency(project: project, config: "implementation", depProjectPath: ":server:modules:premiumModules:dataintegration", depProjectConfig: "apiJarFile") + BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: ":server:modules:ehrModules:ehr", depProjectConfig: "published", depExtension: "module") + BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: ":server:modules:LabDevKitModules:LDK", depProjectConfig: "published", depExtension: "module") + BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: ":server:modules:premiumModules:dataintegration", depProjectConfig: "published", depExtension: "module") + BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: ":server:modules:premiumModules:bigiron", depProjectConfig: "published", depExtension: "module") + BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: ":server:modules:premiumModules:ldap", depProjectConfig: "published", depExtension: "module") + BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: ":server:modules:premiumModules:premium", depProjectConfig: "published", depExtension: "module") + BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: ":server:modules:premiumModules:professional", depProjectConfig: "published", depExtension: "module") + } + +tasks.named('module').configure { dependsOn(project(":server:modules:LabDevKitModules:LDK").tasks.module) } diff --git a/nbri_ehr/module.properties b/nbri_ehr/module.properties new file mode 100644 index 0000000..4260562 --- /dev/null +++ b/nbri_ehr/module.properties @@ -0,0 +1,2 @@ +ModuleClass: org.labkey.nbri_ehr.NBRI_EHRModule +ManageVersion: true diff --git a/nbri_ehr/resources/data/abdominal_obs_types.tsv b/nbri_ehr/resources/data/abdominal_obs_types.tsv new file mode 100644 index 0000000..2a02c74 --- /dev/null +++ b/nbri_ehr/resources/data/abdominal_obs_types.tsv @@ -0,0 +1,8 @@ +value sort_order +Abdominal Distension 1 +Normal Abdominal Palpation 2 +Abnormal Abdominal Palpation 3 +Hepatomegaly (enlarged liver) 4 +Firm or Tense Abdomen 5 +No Abdominal Abnormality Observed 6 +Other Abdominal Abnormality 7 \ No newline at end of file diff --git a/nbri_ehr/resources/data/abnormal_behavior_types.tsv b/nbri_ehr/resources/data/abnormal_behavior_types.tsv new file mode 100644 index 0000000..52daea9 --- /dev/null +++ b/nbri_ehr/resources/data/abnormal_behavior_types.tsv @@ -0,0 +1,7 @@ +value sort_order +SIB 1 +Hair Plucking 2 +Biting Without Injury 3 +Aggression 4 +Stereotypy 5 +Other Behavior Abnormality 6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/acquisition_type.tsv b/nbri_ehr/resources/data/acquisition_type.tsv new file mode 100644 index 0000000..ba8ea9a --- /dev/null +++ b/nbri_ehr/resources/data/acquisition_type.tsv @@ -0,0 +1,6 @@ +value +Captive Bred Import +Feral Import +Lab Transfer (Wild Born) +Native Born (NBRI) +Native Born (US Born - Other colony) \ No newline at end of file diff --git a/nbri_ehr/resources/data/activity.tsv b/nbri_ehr/resources/data/activity.tsv new file mode 100644 index 0000000..b0487b9 --- /dev/null +++ b/nbri_ehr/resources/data/activity.tsv @@ -0,0 +1,7 @@ +value sort_order +0 Unresponsive 1 +0-1 Extremely Lethargic 2 +1 Lethargic 3 +1-2 Slightly Lethargic 4 +2 Normal 5 +Sedated 6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/ageclass.tsv b/nbri_ehr/resources/data/ageclass.tsv new file mode 100644 index 0000000..d2cea5c --- /dev/null +++ b/nbri_ehr/resources/data/ageclass.tsv @@ -0,0 +1,79 @@ +label ageclass gender species min max +Infant 1 3 0 0.5 +Juvenile 2 3 0.5 5 +Adult 3 3 5 21 +Senior 4 3 21 + +Infant 1 4 0 0.5 +Juvenile 2 4 0.5 5 +Adult 3 4 5 21 +Senior 4 4 21 + +Infant 1 5 0 0.5 +Juvenile 2 5 0.5 5 +Adult 3 5 5 21 +Senior 4 5 21 + +Infant 1 18 0 0.25 +Juvenile 2 18 0.25 1.5 +Adult 3 18 1.5 8 +Senior 4 18 8 + +Infant 1 10 0 1 +Juvenile 2 1 10 1 4 +Juvenile 2 2 10 1 4 +Juvenile 2 3 10 1 5 +Adult 3 1 10 4 18 +Adult 3 2 10 4 18 +Adult 3 3 10 5 18 +Senior 4 10 18 + +Infant 1 13 0 1 +Juvenile 2 1 13 1 4 +Juvenile 2 2 13 1 4 +Juvenile 2 3 13 1 5 +Adult 3 1 13 4 18 +Adult 3 2 13 4 18 +Adult 3 3 13 5 18 +Senior 4 13 18 + +Infant 1 2 0 1 +Juvenile 2 1 2 1 4 +Juvenile 2 2 2 1 4 +Juvenile 2 3 2 1 5 +Adult 3 1 2 4 18 +Adult 3 2 2 4 18 +Adult 3 3 2 5 18 +Senior 4 2 18 + +Infant 1 7 0 1 +Juvenile 2 1 7 1 4 +Juvenile 2 2 7 1 4 +Juvenile 2 3 7 1 5 +Adult 3 1 7 4 18 +Adult 3 2 7 4 18 +Adult 3 3 7 5 18 +Senior 4 7 18 + +Infant 1 9 0 1 +Juvenile 2 1 9 1 4 +Juvenile 2 2 9 1 4 +Juvenile 2 3 9 1 5 +Adult 3 1 9 4 18 +Adult 3 2 9 4 18 +Adult 3 3 9 5 18 +Senior 4 9 18 + +Infant 1 6 0 5 +Juvenile 2 6 5 7 +Adult 3 6 7 34 +Senior 4 6 34 + +Infant 1 12 0 1 +Juvenile 2 12 1 3 +Adult 3 12 3 + +Infant 1 19 0 0.25 +Juvenile 2 19 0.25 1.5 +Adult 3 19 1.5 8 +Senior 4 19 8 \ No newline at end of file diff --git a/nbri_ehr/resources/data/alias_category.tsv b/nbri_ehr/resources/data/alias_category.tsv new file mode 100644 index 0000000..fcd8485 --- /dev/null +++ b/nbri_ehr/resources/data/alias_category.tsv @@ -0,0 +1,5 @@ +Value Title Category Description Sort Order Date Disabled +N Nickname +M Microchip +T Old Tattoo +I ISIS Stud Book Number \ No newline at end of file diff --git a/nbri_ehr/resources/data/alopecia_regrowth.tsv b/nbri_ehr/resources/data/alopecia_regrowth.tsv new file mode 100644 index 0000000..4a38100 --- /dev/null +++ b/nbri_ehr/resources/data/alopecia_regrowth.tsv @@ -0,0 +1,4 @@ +value sort_order +Yes 1 +No 2 +Not Evaluated 3 \ No newline at end of file diff --git a/nbri_ehr/resources/data/alopecia_score.tsv b/nbri_ehr/resources/data/alopecia_score.tsv new file mode 100644 index 0000000..2c4a408 --- /dev/null +++ b/nbri_ehr/resources/data/alopecia_score.tsv @@ -0,0 +1,6 @@ +value title sort_order description Date Disabled +Very good coat condition (1) Very good coat condition (1) 1 +1-25% hair loss (2) 1-25% hair loss (2) 2 +25-50% hair loss (3) 25-50% hair loss (3) 3 +More than 50% (4) More than 50% (4) 4 +Completely bald (5) Completely bald (5) 5 \ No newline at end of file diff --git a/nbri_ehr/resources/data/alopecia_type.tsv b/nbri_ehr/resources/data/alopecia_type.tsv new file mode 100644 index 0000000..42be6ed --- /dev/null +++ b/nbri_ehr/resources/data/alopecia_type.tsv @@ -0,0 +1,10 @@ +value sort_order +Thin 1 +Patchy 2 +Bald 3 +Thin and patchy 4 +Thin and bald 5 +Patchy and bald 6 +Thin, patchy and bald 7 +N/A 8 +Not Evaluated 9 \ No newline at end of file diff --git a/nbri_ehr/resources/data/amount_units.tsv b/nbri_ehr/resources/data/amount_units.tsv new file mode 100644 index 0000000..880b273 --- /dev/null +++ b/nbri_ehr/resources/data/amount_units.tsv @@ -0,0 +1,14 @@ +Unit +g +gummy +IU +mcg +mEq +mg +mL +no units +ounces +scoop +tablet +ug +units diff --git a/nbri_ehr/resources/data/app_score.tsv b/nbri_ehr/resources/data/app_score.tsv new file mode 100644 index 0000000..9847f19 --- /dev/null +++ b/nbri_ehr/resources/data/app_score.tsv @@ -0,0 +1,6 @@ +value +NPO +Normal +Normal to low +Low +Unknown \ No newline at end of file diff --git a/nbri_ehr/resources/data/arrival_type.tsv b/nbri_ehr/resources/data/arrival_type.tsv new file mode 100644 index 0000000..7a69edd --- /dev/null +++ b/nbri_ehr/resources/data/arrival_type.tsv @@ -0,0 +1,3 @@ +value +Non-quarantine Arrival +Quarantine Arrival \ No newline at end of file diff --git a/nbri_ehr/resources/data/att_score.tsv b/nbri_ehr/resources/data/att_score.tsv new file mode 100644 index 0000000..8c75361 --- /dev/null +++ b/nbri_ehr/resources/data/att_score.tsv @@ -0,0 +1,6 @@ +value +BAR +QAR +Lethargic +Sedated +Unknown \ No newline at end of file diff --git a/nbri_ehr/resources/data/bandage_observations.tsv b/nbri_ehr/resources/data/bandage_observations.tsv new file mode 100644 index 0000000..f206952 --- /dev/null +++ b/nbri_ehr/resources/data/bandage_observations.tsv @@ -0,0 +1,4 @@ +value sort_order +Intact 1 +Removed or partially removed 2 +Other 3 \ No newline at end of file diff --git a/nbri_ehr/resources/data/bcs_score.tsv b/nbri_ehr/resources/data/bcs_score.tsv new file mode 100644 index 0000000..4f02d84 --- /dev/null +++ b/nbri_ehr/resources/data/bcs_score.tsv @@ -0,0 +1,10 @@ +value title category description sort_order date_disabled +Emaciated (1) 1 +Very Thin (1.5) 2 +Thin (2) 3 +Lean (2.5) 4 +Optimum (3) 5 +Slightly Overweight (3.5) 6 +Heavy (4) 7 +Obese (4.5) 8 +Grossly Obese (5) 9 diff --git a/nbri_ehr/resources/data/behavior_abnormality.tsv b/nbri_ehr/resources/data/behavior_abnormality.tsv new file mode 100644 index 0000000..4daafa5 --- /dev/null +++ b/nbri_ehr/resources/data/behavior_abnormality.tsv @@ -0,0 +1,7 @@ +value sort_order +SIB 1 +Hair plucking 2 +Biting without injury 3 +Aggression 4 +Stereotypy 5 +Other behavior abnormality 6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/behavior_mgmt_codes.tsv b/nbri_ehr/resources/data/behavior_mgmt_codes.tsv new file mode 100644 index 0000000..60efc6e --- /dev/null +++ b/nbri_ehr/resources/data/behavior_mgmt_codes.tsv @@ -0,0 +1,4 @@ +value title sort_order description Date Disabled +No Fleece Tube No Fleece Tube 1 +Fleece Tube Fleece Tube 2 +Wood Wood 3 \ No newline at end of file diff --git a/nbri_ehr/resources/data/behavior_types.tsv b/nbri_ehr/resources/data/behavior_types.tsv new file mode 100644 index 0000000..1162005 --- /dev/null +++ b/nbri_ehr/resources/data/behavior_types.tsv @@ -0,0 +1,6 @@ +value sort_order +Urine drinking 1 +Eye poke 2 +Copraphagy 3 +Stereotypy 4 +Other 5 \ No newline at end of file diff --git a/nbri_ehr/resources/data/blood_draw_reason.tsv b/nbri_ehr/resources/data/blood_draw_reason.tsv new file mode 100644 index 0000000..75a9424 --- /dev/null +++ b/nbri_ehr/resources/data/blood_draw_reason.tsv @@ -0,0 +1,3 @@ +value title +Clinical Clinical +Research Research \ No newline at end of file diff --git a/nbri_ehr/resources/data/blood_draw_tube_type.tsv b/nbri_ehr/resources/data/blood_draw_tube_type.tsv new file mode 100644 index 0000000..b0896aa --- /dev/null +++ b/nbri_ehr/resources/data/blood_draw_tube_type.tsv @@ -0,0 +1,5 @@ +type color +EDTA Purple +Heparin Green +No Additive Red +SST Striped diff --git a/nbri_ehr/resources/data/blood_sample_type.tsv b/nbri_ehr/resources/data/blood_sample_type.tsv new file mode 100644 index 0000000..ee6e939 --- /dev/null +++ b/nbri_ehr/resources/data/blood_sample_type.tsv @@ -0,0 +1,3 @@ +value +Whole Blood +Bone Marrow \ No newline at end of file diff --git a/nbri_ehr/resources/data/blood_tube_volumes.tsv b/nbri_ehr/resources/data/blood_tube_volumes.tsv new file mode 100644 index 0000000..7128a3e --- /dev/null +++ b/nbri_ehr/resources/data/blood_tube_volumes.tsv @@ -0,0 +1,8 @@ +tube_types volume +EDTA 0.5 +EDTA 2.0 +EDTA 3.0 +SST 3.5 +Heparin 4.0 +SST 5.0 +EDTA,Heparin 6.0 diff --git a/nbri_ehr/resources/data/cage_type.tsv b/nbri_ehr/resources/data/cage_type.tsv new file mode 100644 index 0000000..aaf6fb6 --- /dev/null +++ b/nbri_ehr/resources/data/cage_type.tsv @@ -0,0 +1,8 @@ +cagetype height sqft cageslots verticalSlots supportsTunnel +Double - 1 40 7 2 1 false +Double - 2 40 6 2 1 false +Quad - A 50 8 4 1 false +Quad - B 50 9 4 1 false +Quad - C 50 10 4 1 false +Tunnel - I 30 12 2 1 true +Tunnel - II 30 11 2 1 true \ No newline at end of file diff --git a/nbri_ehr/resources/data/calculated_status_codes.tsv b/nbri_ehr/resources/data/calculated_status_codes.tsv new file mode 100644 index 0000000..4989681 --- /dev/null +++ b/nbri_ehr/resources/data/calculated_status_codes.tsv @@ -0,0 +1,7 @@ +code +Alive +Alive - In Progress +Dead +ERROR +No Record +Shipped \ No newline at end of file diff --git a/nbri_ehr/resources/data/capillary_refill_time.tsv b/nbri_ehr/resources/data/capillary_refill_time.tsv new file mode 100644 index 0000000..c82fdd3 --- /dev/null +++ b/nbri_ehr/resources/data/capillary_refill_time.tsv @@ -0,0 +1,3 @@ +value sort_order +<2 sec (normal) 1 +Abnormal 2 \ No newline at end of file diff --git a/nbri_ehr/resources/data/card_format.tsv b/nbri_ehr/resources/data/card_format.tsv new file mode 100644 index 0000000..b786d2c --- /dev/null +++ b/nbri_ehr/resources/data/card_format.tsv @@ -0,0 +1,4 @@ +value title description +1 Default01 Initial Setup +2 Study Chimp Study Chimp Format +3 Study Monkey diff --git a/nbri_ehr/resources/data/census_activity_status.tsv b/nbri_ehr/resources/data/census_activity_status.tsv new file mode 100644 index 0000000..2fc4783 --- /dev/null +++ b/nbri_ehr/resources/data/census_activity_status.tsv @@ -0,0 +1,4 @@ +value title +I In +N New +O Out diff --git a/nbri_ehr/resources/data/conc_units.tsv b/nbri_ehr/resources/data/conc_units.tsv new file mode 100644 index 0000000..eb6660f --- /dev/null +++ b/nbri_ehr/resources/data/conc_units.tsv @@ -0,0 +1,18 @@ +Unit Denominator Numerator +g/gummy gummy g +g/mL mL g +g/tablet tablet g +g/tsp tsp g +IU/mL mL IU +mcg/mL mL mcg +mEq/mL mL mEq +mg/capsule capsule(s) mg +mg/implant implant mg +mg/kg kg mg +mg/mL mL mg +mg/piece piece(s) mg +mg/tablet tablet(s) mg +mg/tsp tsp mg +mL/kg kg mL +ug/mL mL ug +units/mL mL units diff --git a/nbri_ehr/resources/data/cost_type.tsv b/nbri_ehr/resources/data/cost_type.tsv new file mode 100644 index 0000000..e7db0fe --- /dev/null +++ b/nbri_ehr/resources/data/cost_type.tsv @@ -0,0 +1,3 @@ +value title +1 Indirect Cost +2 Direct Cost \ No newline at end of file diff --git a/nbri_ehr/resources/data/country.tsv b/nbri_ehr/resources/data/country.tsv new file mode 100644 index 0000000..97436ea --- /dev/null +++ b/nbri_ehr/resources/data/country.tsv @@ -0,0 +1,9 @@ +value title category +1 St. Kitts 2 +2 Italy 2 +3 Japan 2 +4 "U.S.A." 1 +5 Philippines 2 +6 Indonesia 2 +7 China 2 +8 Mauritius 2 \ No newline at end of file diff --git a/nbri_ehr/resources/data/country_category.tsv b/nbri_ehr/resources/data/country_category.tsv new file mode 100644 index 0000000..95b2d52 --- /dev/null +++ b/nbri_ehr/resources/data/country_category.tsv @@ -0,0 +1,3 @@ +value title +1 Domestic +2 Foreign diff --git a/nbri_ehr/resources/data/daily_enrich_codes.tsv b/nbri_ehr/resources/data/daily_enrich_codes.tsv new file mode 100644 index 0000000..8705eaf --- /dev/null +++ b/nbri_ehr/resources/data/daily_enrich_codes.tsv @@ -0,0 +1,13 @@ +value title sort_order description Date Disabled +Cone Cone 1 +Cap Feeder Cap Feeder 2 +Blind Forager Blind Forager 3 +Dried Fruit Dried Fruit 4 +Forage on Board Forage on Board 5 +Forage Tray Forage Tray 6 +Produce Produce 7 +Paper Burrito Paper Burrito 8 +Puzzle Feeder Puzzle Feeder 9 +Paper Paper 10 +Fleece Tube Replaced Fleece Tube Replaced 11 +Other Other 12 \ No newline at end of file diff --git a/nbri_ehr/resources/data/data_category.tsv b/nbri_ehr/resources/data/data_category.tsv new file mode 100644 index 0000000..102abe7 --- /dev/null +++ b/nbri_ehr/resources/data/data_category.tsv @@ -0,0 +1,5 @@ +value +Clinical +Surgical +Behavior +Research \ No newline at end of file diff --git a/nbri_ehr/resources/data/death_reason.tsv b/nbri_ehr/resources/data/death_reason.tsv new file mode 100644 index 0000000..0b39f78 --- /dev/null +++ b/nbri_ehr/resources/data/death_reason.tsv @@ -0,0 +1,6 @@ +value title +1 Euthanasia (clinical) +2 Euthaniasia (project) +3 Morbid +4 Natural Death +5 Program Management \ No newline at end of file diff --git a/nbri_ehr/resources/data/delivery_state.tsv b/nbri_ehr/resources/data/delivery_state.tsv new file mode 100644 index 0000000..5dc581f --- /dev/null +++ b/nbri_ehr/resources/data/delivery_state.tsv @@ -0,0 +1,5 @@ +value title +0 Template +1 Pending +2 Received +3 Cancelled \ No newline at end of file diff --git a/nbri_ehr/resources/data/dental_obs.tsv b/nbri_ehr/resources/data/dental_obs.tsv new file mode 100644 index 0000000..a4d1da6 --- /dev/null +++ b/nbri_ehr/resources/data/dental_obs.tsv @@ -0,0 +1,7 @@ +value sort_order +Fractured Tooth 1 +Gingival Hyperplasia 2 +Foreign Object in Cheek Pouch 3 +Tooth Abscess 4 +No Dental/Oral Abnormality Observed 5 +Other Dental/Oral Abnormality 6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/derm_obs.tsv b/nbri_ehr/resources/data/derm_obs.tsv new file mode 100644 index 0000000..cfd9bb3 --- /dev/null +++ b/nbri_ehr/resources/data/derm_obs.tsv @@ -0,0 +1,6 @@ +value sort_order +Dermatitis 1 +Erythema (pink or red skin) 2 +Skin Ulceration 3 +No Dermatologic Abnormality Observed 4 +Other Dermatologic Abnormality 5 \ No newline at end of file diff --git a/nbri_ehr/resources/data/divider_types.tsv b/nbri_ehr/resources/data/divider_types.tsv new file mode 100644 index 0000000..8800fdb --- /dev/null +++ b/nbri_ehr/resources/data/divider_types.tsv @@ -0,0 +1,6 @@ +divider countAsSeparate countAsPaired countAsBoth isMoveable displaychar short_description bgcolor border_style +Mesh TRUE FALSE TRUE M MESH grey dotted +Solid TRUE FALSE TRUE S solid +Clear TRUE FALSE TRUE C CLEAR solid +No Slide TRUE TRUE TRUE NO yellow none +Pairing Divider TRUE FALSE TRUE P grey solid \ No newline at end of file diff --git a/nbri_ehr/resources/data/dosage_units.tsv b/nbri_ehr/resources/data/dosage_units.tsv new file mode 100644 index 0000000..66cb1ef --- /dev/null +++ b/nbri_ehr/resources/data/dosage_units.tsv @@ -0,0 +1,14 @@ +Unit Numerator Denominator +1/8 scoop/kg 1/8 scoop kg +g/kg g kg +IU/kg IU kg +mcg/kg mcg kg +mEq/kg mEq kg +mg +mg/animal mg animal +mg/kg mg kg +mL/kg ml kg +no units +ounces/kg ounces kg +ug/kg ug kg +units/kg units kg diff --git a/nbri_ehr/resources/data/editable_lookups.tsv b/nbri_ehr/resources/data/editable_lookups.tsv new file mode 100644 index 0000000..90cc8af --- /dev/null +++ b/nbri_ehr/resources/data/editable_lookups.tsv @@ -0,0 +1,140 @@ +sch query category title description +ehr_lookups abdominal_obs_types Clinical Abdominal Observation Types Used in clinical observations. +ehr_lookups abnormal_behavior_types Clinical Abnormal Behavior Observation Types Used in clinical observations. +ehr_lookups acquisition_type Colony Management Acquisition Type Types of acquisition for Arrivals. +ehr_lookups activity Behavior Activity Behavior observation fixed values. +ehr_lookups ageclass Colony Management Age Class "Categories of age, such as infant or adult, by species. Used in various reports grouping animals by age class." +ehr_lookups alias_category Colony Management Alias Category +ehr_lookups alopecia_score Behavior Alopecia Score Behavior observation fixed values. +ehr_lookups alopecia_type Behavior Alopecia Type Behavior observation fixed values. +ehr_lookups alopecia_regrowth Behavior Alopecia Regrowth Behavior observation fixed values. +ehr_lookups amount_units Clinical Amount Units "Used in drugs, treatments given and treatments ordered datasets." +ehr_lookups app_score Behavior Appetite Score Behavior observation fixed values. +ehr_lookups arrival_type Colony Management Arrival Type Types of arrivals. +ehr_lookups arthritis_types Clinical Arthritis Types Clinical observation fixed values. +ehr_lookups att_score Behavior Attitude Score Behavior observation fixed values. +ehr_lookups bandage_observations Clinical Bandage Observations Clinical observation fixed values. +ehr_lookups bcs_score Clinical Body Condition Score Clinical observation fixed values. +ehr_lookups behavior_abnormality Clinical Behavior Abnormality Clinical observation fixed values. +ehr_lookups behavior_mgmt_codes Behavior Behavior Management Codes Behavior observation fixed values. +ehr_lookups behavior_types Behavior Behavior Types Behavior observation fixed values. +ehr_lookups blood_draw_reason Clinical Blood Draw Reason Used in blood draw datasets. +ehr_lookups blood_draw_tube_type Clinical Blood Draw Tube Type Used in blood draw datasets. +ehr_lookups blood_sample_type Clinical Blood Sample Types Used in blood draw datasets. +ehr_lookups blood_tube_volumes Clinical Blood Tube Volumes Used in blood draw datasets. +ehr_lookups cage_type Colony Management Cage Type Used in cage details. +ehr_lookups calculated_status_codes Colony Management Calculated Status Animal status values. +ehr_lookups capillary_refill_time Clinical Capillary Refill Times Used clinical observations. +ehr_lookups card_format Colony Management Card Format +ehr_lookups census_activity_status Colony Management Census Activity Status +ehr_lookups clinremarks_category Clinical Clinical Remark Category Clinical remarks category. +ehr_lookups conc_units Clinical Concentration Units Used in drug and treatment datasets. +ehr_lookups congenital_abnormalities Clinical Congenital Abnormalities Clinical observation fixed values. +ehr_lookups cost_center Colony Management Cost Center +ehr_lookups cost_type Colony Management Cost Type +ehr_lookups country Colony Management Country +ehr_lookups country_category Colony Management Country Category +ehr_lookups daily_enrich_codes Behavior Daily enrichment codes. +ehr_lookups data_category Clinical Data Categories Used in datasets. +ehr_lookups death_reason Colony Management Death Reason +ehr_lookups delivery_state Colony Management Delivery State +ehr_lookups dental_obs Clinical Dental Observation Types Clinical observation values. +ehr_lookups derm_obs Clinical Dermatologic Observation Types Clinical observation values. +ehr_lookups digit_amputation Clinical Digit Amputation Clinical observation fixed values. +ehr_lookups divider_types Colony Management Divider Type Used in cage details. +ehr_lookups dosage_units Clinical Dosage Units Used in drug and treatment datasets. +ehr_lookups drug_defaults Clinical Formulary Default values in drug and treatment datasets. +ehr_lookups ear_types Clinical Ear Types Clinical observation fixed values. +ehr_lookups esig_events Colony Management Esig Events +ehr_lookups euthanasia_type Colony Management Euthanasia Type +ehr_lookups exam_findings Clinical Exam Findings Physical exam values. +ehr_lookups exemption_category Colony Management Exemption Category +ehr_lookups expense_class Colony Management Expense Class +ehr_lookups fecal_score Clinical Fecal Score Clinical observation fixed values. +ehr_lookups fecal_smear_score Clinical Fecal Smear Score Clinical observation fixed values. +ehr_lookups feed_assess_types Behavior Fecal Assessment Types Behavior observation fixed values. +ehr_lookups flag_categories Colony Management Flag Categories Used to specify flag behavior. +ehr_lookups flag_values Colony Management Flag Values Animal flag values. +ehr_lookups gastro_types Clinical Gastrointestinal Types Clinical observation fixed values. +ehr_lookups gender_codes Colony Management Sex Codes Used in demographics dataset. +ehr_lookups general_obs Clinical General Observation Types Clinical observation types. +ehr_lookups genital_types Colony Management Genital Types Clinical observation fixed values. +ehr_lookups genitourinary_obs Clinical Genitourinary Observation Types Clinical observation fixed values. +ehr_lookups geographic_origins Colony Management Geographic Origins Used in demographics dataset. +ehr_lookups hernia_types Clinical Hernia Types Clinical observation fixed values. +ehr_lookups housing_reason Housing Housing Move Reason Used in housing dataset for location transfers. +ehr_lookups hyd_score Clinical Hydration Score Clinical observation fixed values. +ehr_lookups id_history_type Colony Management Id History Type +ehr_lookups incision_score Clinical Incision Status Clinical observation fixed values. +ehr_lookups indoor_outdoor Colony Management Indoor/Outdoor Cage details +ehr_lookups keyword Clinical Keyword Clinical observation fixed values. +ehr_lookups lameness Clinical Lameness Clinical observation fixed values. +ehr_lookups mass_type Clinical Mass Type Clinical observation fixed values. +ehr_lookups mens_score Clinical Menses Types Clinical observation fixed values. +ehr_lookups mucous_membranes Clinical Mucous Membranes Used in clinical observations. +ehr_lookups musculoskeletal_observations Clinical Musculoskeletal Observations Used in clinical observations. +ehr_lookups necropsy_disposition_codes Colony Management Necropsy Disposition Codes +ehr_lookups necropsy_organ_appearance Colony Management Necropsy Organ Appearance +ehr_lookups necropsy_organ_systems Colony Management Necropsy Organ Systems +ehr_lookups necropsy_physical_condition Colony Management Necropsy Physical Condition +ehr_lookups necropsy_specimen_condition Colony Management Necropsy Specimen Condition +ehr_lookups necropsy_tissue Colony Management Necropsy Tissue +ehr_lookups neurologic_observations Clinical Neurologic Observations Used in clinical observations.. +ehr_lookups nhp_training_reason Behavior NHP Training Reason Behavior training reason values +ehr_lookups nhp_training_result Behavior NHP Training Result Behavior training result values +ehr_lookups nhp_training_type Behavior NHP Training Type Behavior training type values +ehr_lookups normal_abnormal_only Clinical Normal/Abnormal Values Clinical observation values. +ehr_lookups numeric_unit Colony Management Numeric Unit +ehr_lookups observation_areas Clinical Observation Areas Clinical observation areas. +ehr_lookups obstetric_observations Clinical Obstetric Observations Obstetric Observations Fixed Values. +ehr_lookups ocular_observations Clinical Ocular Observations Ocular Observations Fixed Values. +ehr_lookups ocular_problem Clinical Ocular Problem Clinical observation fixed values. +ehr_lookups pairing_formation_types Behavior Pairing Formation Type Pairing formation values. +ehr_lookups pairing_goal Behavior Pairing Goal Used in pairing dataset. +ehr_lookups pairing_reason Behavior Introduction Reason Used in pairing dataset. +ehr_lookups pairing_observation Behavior Interaction Summary Used in pairing dataset. +ehr_lookups pairing_separation_reason Colony Management Pairing Status Change Reason Pairing Status Change Reason Fixed Values. +ehr_lookups preferences Behavior Preferences Behavior observation fixed values. +ehr_lookups pregnancy_result Colony Management Pregancy Result +ehr_lookups procedure_category Clinical Procedure Category Used in procedures to group procedures. +ehr_lookups procedures Clinical Procedures List of animal procedures.F +ehr_lookups problem_list_category Clinical Problem List Category Used in problem list dataset. Set when opening a case. +ehr_lookups problem_list_subcategory Clinical Problem List Subcategory Used in problem list to categorize problems. +ehr_lookups protocol_category Colony Management Protocol Category +ehr_lookups protocol_state Colony Management Protocol State +ehr_lookups protocol_type Colony Management Protocol Type +ehr_lookups qualifier Colony Management Qualifier +ehr_lookups questionnaire Colony Management Questionnaire +ehr_lookups rectal_prolapse Clinical Rectal Prolapse Used in clinical observations. +ehr_lookups regulatory_stress_levels Colony Management Regulatory Stress Levels +ehr_lookups req_order_state Colony Management Request Order State +ehr_lookups req_order_type Colony Management Request Order Type +ehr_lookups respiratory_observations Clinical Respiratory Observations Used in clinical observations. +ehr_lookups routes Clinical Treatment Routes Used in drug and treatment datasets. +ehr_lookups sib_score Behavior SIB Score Behavior observation fixed values. +ehr_lookups skin_problem Clinical Skin Problems Clinical observation fixed values. +ehr_lookups source Colony Management Source +ehr_lookups species Colony Management Species +ehr_lookups snomed Research Treatments List of animal treatments. +ehr_lookups species_codes Colony Management Species Codes +ehr_lookups stool_score Clinical Stool Score +ehr_lookups stool_types Clinical Stool Types +ehr_lookups tb_obs_score Clinical TB Observation Scores Clinical observation fixed values. +ehr_lookups temperament Behavior Temperament Behavior observation fixed values. +ehr_lookups testicular_volume Clinical Testicular Volume Testicular volume values. +ehr_lookups termination_reason_codes Clinical Termination Reason Codes Clinical observation fixed values. +ehr_lookups trauma_size Clinical Trauma Size Clinical observation fixed values. +ehr_lookups treatment_frequency Clinical Treatment Frequency Used in treatment and drug datasets. +ehr_lookups treatment_frequency_times Clinical Treatment Frequency Times "Used in treatment, drug and observation datasets." +ehr_lookups turgor_score Clinical Turgor Score Clinical observation fixed values. +ehr_lookups vaginal_uterine_prolapse Clinical Vaginal Uterine Prolapse Clinical observation fixed values. +ehr_lookups vendor_approval_code Colony Management Vendor Approval Code +ehr_lookups vendor_production_location Colony Management Vendor Production Location +ehr_lookups volume_units Clinical Volume Units Used in drug and treatment datasets. +ehr_lookups weight_ranges Clinical Weight Ranges Min/Max allowable weight per species. Used in various weight reports. +ehr_lookups wound_score Clinical Wound Score Clinical observation fixed values. +ehr_lookups wound_severity Clinical Wound Severity Clinical observation fixed values. +ehr_lookups wound_status_behavior Behavior Wound Status Behavioral observation fixed values. +ehr_lookups wound_status_clinical Clinical Wound Status Clinical observation fixed values. +ehr_lookups yes_no_order Clinical Yes/No Values in Order Used for yes/no values in various datasets. Includes sort order. +ehr_lookups yes_no_only Clinical Yes/No Forced Selection Must choose yes or no. diff --git a/nbri_ehr/resources/data/esig_events.tsv b/nbri_ehr/resources/data/esig_events.tsv new file mode 100644 index 0000000..5c099f6 --- /dev/null +++ b/nbri_ehr/resources/data/esig_events.tsv @@ -0,0 +1,16 @@ +value title description +1 Submit Protocol Request Submit Protocol Request +2 Question Answered Question Answered +3 Pre-Submission Pre-Submission +4 Designated Reviewer Approval Set Final Vote +5 Return for Modification Return for Modification +6 Assign Review Tier Assign Review Tier +7 Submit Opinion Render a Vote +8 Receive Animal Shipments Receive Animal Shipments +9 Transfer Animals Transfer Animals +10 Record Training Results Record Training Results +11 Submit Animal Order Request Submit Animal Order Request +12 Approve/Not Approve Animal Order Request Approve/Not Approve Animal Order Request +13 Global Protocol Deletion +14 Global Account Deletion +15 Unreceive Animal Shipment. Unreceive Animal Shipment \ No newline at end of file diff --git a/nbri_ehr/resources/data/euthanasia_type.tsv b/nbri_ehr/resources/data/euthanasia_type.tsv new file mode 100644 index 0000000..c021231 --- /dev/null +++ b/nbri_ehr/resources/data/euthanasia_type.tsv @@ -0,0 +1,5 @@ +value title +1 Sedate and exsanguinate +2 Gas anesthesia (isoflurane) +3 Lethal Injection (pentobarbital) + diff --git a/nbri_ehr/resources/data/exam_findings.tsv b/nbri_ehr/resources/data/exam_findings.tsv new file mode 100644 index 0000000..f2e67cc --- /dev/null +++ b/nbri_ehr/resources/data/exam_findings.tsv @@ -0,0 +1,3 @@ +value +No significant findings +See remarks diff --git a/nbri_ehr/resources/data/exemption_category.tsv b/nbri_ehr/resources/data/exemption_category.tsv new file mode 100644 index 0000000..50e3262 --- /dev/null +++ b/nbri_ehr/resources/data/exemption_category.tsv @@ -0,0 +1,9 @@ +value title +Food Exempt-Behavioral-Not Permanent Food Exempt-Behavioral-Not Permanent +Housing Exempt-Behavioral-Not Permanent Housing Exempt-Behavioral-Not Permanent +Housing Exempt-Behavioral-Permanent Housing Exempt-Behavioral-Permanent +Housing Exempt-Clinical-Not Permanent Housing Exempt-Clinical-Not Permanent +Housing Exempt-Clinical-Permanent Housing Exempt-Clinical-Permanent +Housing Exempt-Other-Not Permanent Housing Exempt-Other-Not Permanent +Housing Exempt-Released Housing Exempt-Released +Housing Exempt-Research Housing Exempt-Research \ No newline at end of file diff --git a/nbri_ehr/resources/data/expense_class.tsv b/nbri_ehr/resources/data/expense_class.tsv new file mode 100644 index 0000000..371ca83 --- /dev/null +++ b/nbri_ehr/resources/data/expense_class.tsv @@ -0,0 +1,32 @@ +value title description +1 1500 Labor +2 1998 Fringe +3 1999 Overhead +4 2000 Animals +5 2005 Feed +6 2006 Nutritional Supplements +7 2020 Animal Bedding +8 2021 Apparel +9 2022 Colony Supplies +10 2023 Clinical Supplies +11 2024 Laboratory Supplies +12 2025 Contract Laboratory +13 2026 Protective Disposables +14 2029 Other Operating Supplies +15 2040 Equipment Repair/Prototype +16 2041 Facilities/Safety Modifications +17 2042 Operating Services +18 2043 Utilities +19 2044 Professional Services +20 2050 Rentals +21 2060 Shipping/Receiving Animals +22 2061 Mail/Express +23 2065 Meetings +24 2066 Other Travel Expenses +25 2080 Office Supplies +26 2081 Computer Supplies +27 2082 Educational Materials/Memberships +28 2083 Medical Illustrations +29 2090 Telephone +30 4000 Fixed Equippment +31 9999 Fee \ No newline at end of file diff --git a/nbri_ehr/resources/data/fecal_smear_score.tsv b/nbri_ehr/resources/data/fecal_smear_score.tsv new file mode 100644 index 0000000..68e8207 --- /dev/null +++ b/nbri_ehr/resources/data/fecal_smear_score.tsv @@ -0,0 +1,6 @@ +value +0 +1 +2 +3 +4 \ No newline at end of file diff --git a/nbri_ehr/resources/data/feed_assess_types.tsv b/nbri_ehr/resources/data/feed_assess_types.tsv new file mode 100644 index 0000000..ad5f282 --- /dev/null +++ b/nbri_ehr/resources/data/feed_assess_types.tsv @@ -0,0 +1,4 @@ +Value Title Category Description Sort Order Date Disabled +Increase Feed +Decrease Feed +Maintain Feed \ No newline at end of file diff --git a/nbri_ehr/resources/data/gender_codes.tsv b/nbri_ehr/resources/data/gender_codes.tsv new file mode 100644 index 0000000..01c67fb --- /dev/null +++ b/nbri_ehr/resources/data/gender_codes.tsv @@ -0,0 +1,4 @@ +code meaning +1 unknown +2 female +3 male \ No newline at end of file diff --git a/nbri_ehr/resources/data/general_obs.tsv b/nbri_ehr/resources/data/general_obs.tsv new file mode 100644 index 0000000..3f77073 --- /dev/null +++ b/nbri_ehr/resources/data/general_obs.tsv @@ -0,0 +1,7 @@ +value sort_order +Edema 1 +Petechiae (pinpoint hemorrhages) 2 +Ecchymosis (bruising) 3 +Obtunded Demeanor (dull responses to stimuli) 4 +AV Fistula 5 +Other General Observations 6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/genitourinary_obs.tsv b/nbri_ehr/resources/data/genitourinary_obs.tsv new file mode 100644 index 0000000..bd30f5b --- /dev/null +++ b/nbri_ehr/resources/data/genitourinary_obs.tsv @@ -0,0 +1,7 @@ +value sort_order +Blood Urine 1 +Dribbling Urine 2 +Distended Bladder 3 +Penile/Preputial Lesions 4 +No Genitourinary Abnormality Observed 5 +Other Genitourinary Abnormality 6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/geographic_origins.tsv b/nbri_ehr/resources/data/geographic_origins.tsv new file mode 100644 index 0000000..aa32806 --- /dev/null +++ b/nbri_ehr/resources/data/geographic_origins.tsv @@ -0,0 +1,32 @@ +meaning +AFRICA +ARABIAN PENINSULA +ARGENTINA +BOLIVIA +BRAZIL +CAMBODIA +CARIBBEAN +CELEBES IS./INDONES +CENTRAL AFRICA +CENTRAL AMERICA +CHINA +COLUMBIA +CONGO +EAST AFRICA +EQUADOR +GHANA +INDIA +INDONESIA +JAPAN +KENYA +MALAGASY REPUBLIC +MAURITIUS, REPUBLIC OF +NIGERIA +ORIGIN UNKNOWN +PERU +PHILIPPINES +RUSSIA +SOUTH AMERICA +SPAIN +THIALAND +USA \ No newline at end of file diff --git a/nbri_ehr/resources/data/hernia_types.tsv b/nbri_ehr/resources/data/hernia_types.tsv new file mode 100644 index 0000000..499f45b --- /dev/null +++ b/nbri_ehr/resources/data/hernia_types.tsv @@ -0,0 +1,5 @@ +value sort_order +Inguinal Hernia on Right Side 1 +Inguinal Hernia on Left Side 2 +Umbilical Hernia 3 +Other 4 \ No newline at end of file diff --git a/nbri_ehr/resources/data/housing_reason.tsv b/nbri_ehr/resources/data/housing_reason.tsv new file mode 100644 index 0000000..356ba3f --- /dev/null +++ b/nbri_ehr/resources/data/housing_reason.tsv @@ -0,0 +1,25 @@ +Value Title Category Description Sort Order Date Disabled +Behavioral Behavioral +Breeding Breeding +Cage Configuration Change Cage Configuration Change +Construction Construction +Environmental conditions Environmental conditions +Husbandry Husbandry +New pair formation New pair formation +Pair formation Mother Surrogate Pair formation Mother Surrogate +Pair separation behavioral Pair separation behavioral +Pair separation clinical Pair separation clinical +Pair separation scientific Pair separation scientific +Quarantine Quarantine +Quarantine Arrival Quarantine Arrival +Non-quarantine Arrival Non-quarantine Arrival +Retirement Retirement +Return to Group Return to Group +Return to Social Partner Return to Social Partner +Room consolidation Room consolidation +Sale Sale +Scientific Scientific +Social group introduction breeding Social group introduction breeding +Social group introduction non-breeding Social group introduction non-breeding +Veterinary Treatment Veterinary Treatment +Weaning Weaning \ No newline at end of file diff --git a/nbri_ehr/resources/data/hyd_score.tsv b/nbri_ehr/resources/data/hyd_score.tsv new file mode 100644 index 0000000..fdac67e --- /dev/null +++ b/nbri_ehr/resources/data/hyd_score.tsv @@ -0,0 +1,7 @@ +value sort_order +0% 1 +0-5% 2 +5% 3 +5-10% 4 +10% 5 +>10% 6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/id_history_type.tsv b/nbri_ehr/resources/data/id_history_type.tsv new file mode 100644 index 0000000..ba59b93 --- /dev/null +++ b/nbri_ehr/resources/data/id_history_type.tsv @@ -0,0 +1,6 @@ +value title +1 Old Tattoo Number +2 ISIS Stud Book Number +3 CITES Number +4 Name +5 Transponder Number \ No newline at end of file diff --git a/nbri_ehr/resources/data/incision_score.tsv b/nbri_ehr/resources/data/incision_score.tsv new file mode 100644 index 0000000..2dd205f --- /dev/null +++ b/nbri_ehr/resources/data/incision_score.tsv @@ -0,0 +1,8 @@ +value sort_order +Healing Well 1 +Seroma 2 +Infection 3 +Hernia 4 +Dehiscence (incision open) 5 +Erythema or Bruising at Incision Site 6 +Other 7 \ No newline at end of file diff --git a/nbri_ehr/resources/data/indoor_outdoor.tsv b/nbri_ehr/resources/data/indoor_outdoor.tsv new file mode 100644 index 0000000..7606761 --- /dev/null +++ b/nbri_ehr/resources/data/indoor_outdoor.tsv @@ -0,0 +1,4 @@ +value sort_order +Indoor 1 +Outdoor 2 +Indoor/Outdoor 3 \ No newline at end of file diff --git a/nbri_ehr/resources/data/lameness.tsv b/nbri_ehr/resources/data/lameness.tsv new file mode 100644 index 0000000..8a3ff33 --- /dev/null +++ b/nbri_ehr/resources/data/lameness.tsv @@ -0,0 +1,5 @@ +value sort_order +Lame on right leg 1 +Lame on left leg 2 +Not using legs 3 +No lameness observed 4 \ No newline at end of file diff --git a/nbri_ehr/resources/data/lookup_sets.tsv b/nbri_ehr/resources/data/lookup_sets.tsv new file mode 100644 index 0000000..613eb8e --- /dev/null +++ b/nbri_ehr/resources/data/lookup_sets.tsv @@ -0,0 +1,118 @@ +setname label keyfield titleColumn +abdominal_obs_types Abdominal Observation Types value +abnormal_behavior_types Abnormal Behavior Types value +acquisition_type Acquisition Type value +activity Activity value +alias_category Alias Category value title +alopecia_type Alopecia Type value +alopecia_score Alopecia Type value +alopecia_regrowth Alopecia Regrowth value +app_score Appetite Score value +arrival_type Arrival Type value +arthritis_types Arthritis Types value +att_score Attitude Score value +bandage_observations Bandage/splint Observations value +bcs_score BCS Store value title +behavior_abnormality Behavior Abnormality value +behavior_mgmt_codes Behavior Management Codes value +behavior_types Behavior Types value +blood_draw_reason Blood Draw Reason value +blood_sample_type Blood Sample Types value +cage_type Cage Type value title +capillary_refill_time Capillary Refill Time value +card_format Card Format value title +census_activity_status Census Activity Status value title +clinremarks_category Clinremarks Category value title +congenital_abnormalities Congenital Abnormalities value title +cost_center Cost Center value title +cost_type Cost Type value title +country Country value title +country_category Country Category value title +daily_enrich_codes Daily Enrichment Codes value +data_category Data Category Field Values value +death_reason Death Reason value +delivery_state Delivery State value title +dental_obs Dental Observations value +derm_obs Dermatologic Observations value +digit_amputation Digit Amputation value title +ear_types Ear Types value title +esig_events ESig Events value title +euthanasia_type Euthanasia Type value title +exam_findings Exam Findings value +exemption_category Exemption Category value title +expense_class Expense Class value description +fecal_score Fecal Score value description +fecal_smear_score Fecal Smear Scores value +feed_assess_types Feed Assessment Types value +gastro_types Gastrointestinal Types value +general_obs General Observations value +genital_types Genital Types value +genitourinary_obs Genitourinary Observations value +hernia_types Hernia Types value +housing_reason Housing Reason value +hyd_score Hyd Score value +id_history_type Id History Type value title +incision_score Incision Status value +indoor_outdoor Indoor/Outdoor value +keyword Keyword value title +lameness Lameness value title +mass_type Mass Type value title +mens_score Menses value +mucous_membranes Mucous Membranes value +musculoskeletal_observations Musculoskeletal Observations value +necropsy_disposition_codes Tissue Disposition Codes value title +necropsy_organ_appearance Appearance value title +necropsy_organ_systems Organ Systems value title +necropsy_physical_condition Physical Condition value title +necropsy_specimen_condition Specimen Condition value title +necropsy_tissue Tissues value title +neurologic_observations Neurologic Observations value +nhp_training_reason NHP Training Reason value +nhp_training_result NHP Training Result value +nhp_training_type NHP Training Type value +normal_abnormal_only Normal/Abnormal Type value +numeric_unit Numeric Units value title +obstetric_observations Obstetric Observations value +ocular_observations Ocular Observations value +observation_areas Observation Areas value +ocular_problem Ocular Problem value +pairing_goal Pairing Goal value +pairing_formation_types Pairing Formation Type value +pairing_reason Introduction Reason value +pairing_observation Interaction Summary value +pairing_separation_reason Pairing Status Change Reason value value +preferences Preferences value +pregnancy_result Pregnancy Results value +procedure_category Category of procedures value +problem_list_category Problem List Category value +problem_list_subcategory Problem List Sub-Category value +protocol_category Protocol Category value title +protocol_state Protocol State value title +protocol_type Protocol Type value title +qualifier Qualifier value title +questionnaire Questionnaire value title +rectal_prolapse Rectal Prolapse value +regulatory_stress_levels Regulatory Stress Levels value title +req_order_state Req Order State value title +req_order_type Req Order Type value title +respiratory_observations Respiratory Observations value title +sib_score SIB Score value +skin_problem Skin Problem value +stool_score Stool Score value +stool_types Stool Types value +tb_obs_score TB Obs Score value +temperament Temperament value title +testicular_volume Testicular Volume value title +trauma_size Trauma Size value +turgor_score Turgor Score value +termination_reason_codes Termination Reason Codes Codes value title +vendor_approval_code Vendor Approval Code value title +vaginal_uterine_prolapse Vaginal Uterine Prolapse value +vendor_production_location Vendor Production Location value title +weight_ranges Weight Ranges value +wound_score Wound Score value +wound_severity Wound Severity value +wound_status_behavior Wound Status Behavior value +wound_status_clinical Wound Status Clinical value +yes_no_order Yes/No Values in Order value +yes_no_only Yes/No Forced Selection value diff --git a/nbri_ehr/resources/data/lookupsManifest.tsv b/nbri_ehr/resources/data/lookupsManifest.tsv new file mode 100644 index 0000000..defb466 --- /dev/null +++ b/nbri_ehr/resources/data/lookupsManifest.tsv @@ -0,0 +1,131 @@ +name +abdominal_obs_types +abnormal_behavior_types +acquisition_type +activity +ageclass +alias_category +alopecia_type +alopecia_score +alopecia_regrowth +amount_units +app_score +arrival_type +arthritis_types +att_score +bandage_observations +bcs_score +behavior_abnormality +behavior_mgmt_codes +behavior_types +blood_draw_reason +blood_draw_tube_type +blood_sample_type +blood_tube_volumes +cage_type +calculated_status_codes +capillary_refill_time +card_format +census_activity_status +congenital_abnormalities +conc_units +cost_type +country +country_category +daily_enrich_codes +data_category +death_reason +delivery_state +dental_obs +derm_obs +digit_amputation +divider_types +dosage_units +ear_types +editable_lookups +esig_events +euthanasia_type +exam_findings +exemption_category +expense_class +fecal_score +fecal_smear_score +feed_assess_types +gastro_types +gender_codes +general_obs +genital_types +genitourinary_obs +geographic_origins +hernia_types +housing_reason +hyd_score +id_history_type +incision_score +indoor_outdoor +lameness +mass_type +mens_score +mucous_membranes +musculoskeletal_observations +necropsy_disposition_codes +necropsy_organ_appearance +necropsy_organ_systems +necropsy_physical_condition +necropsy_specimen_condition +necropsy_tissue +neurologic_observations +nhp_training_reason +nhp_training_result +nhp_training_type +normal_abnormal_only +numeric_unit +observation_areas +obstetric_observations +ocular_observations +ocular_problem +pairing_formation_types +pairing_goal +pairing_reason +pairing_observation +pairing_separation_reason +preferences +pregnancy_result +procedure_category +problem_list_category +problem_list_subcategory +protocol_category +protocol_state +protocol_type +qualifier +questionnaire +rectal_prolapse +regulatory_stress_levels +req_order_state +req_order_type +respiratory_observations +routes +sib_score +source +snomed +skin_problem +stool_score +stool_types +tb_obs_score +temperament +testicular_volume +trauma_size +treatment_frequency +treatment_frequency_times +turgor_score +vaginal_uterine_prolapse +vendor_approval_code +vendor_production_location +volume_units +weight_ranges +wound_score +wound_severity +wound_status_behavior +wound_status_clinical +yes_no_only +yes_no_order diff --git a/nbri_ehr/resources/data/lookupsManifestTest.tsv b/nbri_ehr/resources/data/lookupsManifestTest.tsv new file mode 100644 index 0000000..b2006c8 --- /dev/null +++ b/nbri_ehr/resources/data/lookupsManifestTest.tsv @@ -0,0 +1,133 @@ +name +abdominal_obs_types +abnormal_behavior_types +acquisition_type +activity +ageclass +alias_category +alopecia_type +alopecia_score +alopecia_regrowth +amount_units +app_score +arrival_type +arthritis_types +bandage_observations +bcs_score +behavior_abnormality +behavior_mgmt_codes +behavior_types +blood_draw_reason +blood_draw_tube_type +blood_sample_type +blood_tube_volumes +cage_type +calculated_status_codes +capillary_refill_time +card_format +census_activity_status +conc_units +congenital_abnormalities +cost_type +country +country_category +daily_enrich_codes +data_category +death_reason +delivery_state +dental_obs +derm_obs +divider_types +digit_amputation +dosage_units +ear_types +editable_lookups +esig_events +euthanasia_type +exam_findings +exemption_category +expense_class +fecal_score +fecal_smear_score +feed_assess_types +gastro_types +gender_codes +general_obs +genital_types +genitourinary_obs +geographic_origins +hernia_types +housing_reason +hyd_score +id_history_type +incision_score +indoor_outdoor +lameness +mass_type +mens_score +mucous_membranes +musculoskeletal_observations +necropsy_disposition_codes +necropsy_organ_appearance +necropsy_organ_systems +necropsy_physical_condition +necropsy_specimen_condition +necropsy_tissue +neurologic_observations +nhp_training_reason +nhp_training_result +nhp_training_type +normal_abnormal_only +numeric_unit +observation_areas +obstetric_observations +ocular_observations +ocular_problem +pairing_formation_types +pairing_goal +pairing_reason +pairing_observation +pairing_separation_reason +preferences +pregnancy_result +procedure_category +procedures +problem_list_category +problem_list_subcategory +protocol_category +protocol_state +protocol_type +qualifier +questionnaire +rectal_prolapse +regulatory_stress_levels +req_order_state +req_order_type +respiratory_observations +routes +sib_score +skin_problem +source +snomed +species +species_codes +stool_score +stool_types +tb_obs_score +temperament +testicular_volume +trauma_size +treatment_frequency +treatment_frequency_times +turgor_score +vaginal_uterine_prolapse +vendor_approval_code +vendor_production_location +volume_units +weight_ranges +wound_score +wound_severity +wound_status_behavior +wound_status_clinical +yes_no_only +yes_no_order \ No newline at end of file diff --git a/nbri_ehr/resources/data/mens_score.tsv b/nbri_ehr/resources/data/mens_score.tsv new file mode 100644 index 0000000..25e25fd --- /dev/null +++ b/nbri_ehr/resources/data/mens_score.tsv @@ -0,0 +1,4 @@ +value sort_order +Present 1 +Not present 2 +Heavy mense 3 \ No newline at end of file diff --git a/nbri_ehr/resources/data/mucous_membranes.tsv b/nbri_ehr/resources/data/mucous_membranes.tsv new file mode 100644 index 0000000..0e58c42 --- /dev/null +++ b/nbri_ehr/resources/data/mucous_membranes.tsv @@ -0,0 +1,7 @@ +value sort_order +Pink (normal) 1 +Pale 2 +Cyanosis (bluish discoloration) 3 +Icterus (jaundice; yellow discoloration) 4 +Cannot visualize 5 +Other 6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/musculoskeletal_observations.tsv b/nbri_ehr/resources/data/musculoskeletal_observations.tsv new file mode 100644 index 0000000..b3c6d90 --- /dev/null +++ b/nbri_ehr/resources/data/musculoskeletal_observations.tsv @@ -0,0 +1,8 @@ +value sort_order +Muscle atrophy 1 +Fractured limb 2 +Decreased extension of knees 3 +Crepitus (crackling sensation upon palpation) 4 +Kyphosis (spinal curvature; hunchback) 5 +No musculoskeletal abnormality observed 6 +Other musculoskeletal abnormality 7 \ No newline at end of file diff --git a/nbri_ehr/resources/data/necropsy_disposition_codes.tsv b/nbri_ehr/resources/data/necropsy_disposition_codes.tsv new file mode 100644 index 0000000..958ee97 --- /dev/null +++ b/nbri_ehr/resources/data/necropsy_disposition_codes.tsv @@ -0,0 +1,7 @@ +value title +1 Formalin Fixed +2 Frozen +3 Tissue Culture +4 Bacteriology +5 Ship to Sponsor +6 Other \ No newline at end of file diff --git a/nbri_ehr/resources/data/necropsy_exam_reason.tsv b/nbri_ehr/resources/data/necropsy_exam_reason.tsv new file mode 100644 index 0000000..4b7c6ce --- /dev/null +++ b/nbri_ehr/resources/data/necropsy_exam_reason.tsv @@ -0,0 +1,4 @@ +value title +1 Natural Death +2 Euth.-moribund +3 Euth.-project \ No newline at end of file diff --git a/nbri_ehr/resources/data/necropsy_organ_appearance.tsv b/nbri_ehr/resources/data/necropsy_organ_appearance.tsv new file mode 100644 index 0000000..c530f3e --- /dev/null +++ b/nbri_ehr/resources/data/necropsy_organ_appearance.tsv @@ -0,0 +1,3 @@ +value title +1 Normal +2 Abnormal \ No newline at end of file diff --git a/nbri_ehr/resources/data/necropsy_organ_systems.tsv b/nbri_ehr/resources/data/necropsy_organ_systems.tsv new file mode 100644 index 0000000..7f0bc70 --- /dev/null +++ b/nbri_ehr/resources/data/necropsy_organ_systems.tsv @@ -0,0 +1,10 @@ +value title +1 Nervous system +2 Cardiovascular system +3 Respiratory system +4 Digestive system +5 Genitourinary system +6 Lymphatic system +7 Musculoskeletal system +8 Endocrine system +9 Integumentary system \ No newline at end of file diff --git a/nbri_ehr/resources/data/necropsy_physical_condition.tsv b/nbri_ehr/resources/data/necropsy_physical_condition.tsv new file mode 100644 index 0000000..b50cc92 --- /dev/null +++ b/nbri_ehr/resources/data/necropsy_physical_condition.tsv @@ -0,0 +1,4 @@ +value title +1 Excellent +2 Fair +3 Poor \ No newline at end of file diff --git a/nbri_ehr/resources/data/necropsy_specimen_condition.tsv b/nbri_ehr/resources/data/necropsy_specimen_condition.tsv new file mode 100644 index 0000000..6edff69 --- /dev/null +++ b/nbri_ehr/resources/data/necropsy_specimen_condition.tsv @@ -0,0 +1,4 @@ +value title +1 Fresh +2 Refrigerated +3 Autolysis \ No newline at end of file diff --git a/nbri_ehr/resources/data/necropsy_tissue.tsv b/nbri_ehr/resources/data/necropsy_tissue.tsv new file mode 100644 index 0000000..68fa361 --- /dev/null +++ b/nbri_ehr/resources/data/necropsy_tissue.tsv @@ -0,0 +1,17 @@ +value title +1 Blood +2 Brain +3 Cecum +4 Colon +5 Duodenum +6 Heart +7 Ileum +8 Jejunum +9 Pancreas +10 Kidney +11 Stomach +12 Liver +13 Lung +14 Spleen +15 Tracheobronchial l.n. +16 Other \ No newline at end of file diff --git a/nbri_ehr/resources/data/neurologic_observations.tsv b/nbri_ehr/resources/data/neurologic_observations.tsv new file mode 100644 index 0000000..c533b35 --- /dev/null +++ b/nbri_ehr/resources/data/neurologic_observations.tsv @@ -0,0 +1,8 @@ +value sort_order +No neurologic abnormality observed 1 +Seizures 2 +Ataxia (uncoordinated movements) 3 +Head tilt 4 +Intention tremors 5 +Paralysis/Paresis 6 +Other neurologic abnormality 7 \ No newline at end of file diff --git a/nbri_ehr/resources/data/nhp_training_reason.tsv b/nbri_ehr/resources/data/nhp_training_reason.tsv new file mode 100644 index 0000000..f1d9759 --- /dev/null +++ b/nbri_ehr/resources/data/nhp_training_reason.tsv @@ -0,0 +1,6 @@ +value +PI Request +Behavioral Initiated +Clinic +Husbandry +Other \ No newline at end of file diff --git a/nbri_ehr/resources/data/nhp_training_result.tsv b/nbri_ehr/resources/data/nhp_training_result.tsv new file mode 100644 index 0000000..7b240f2 --- /dev/null +++ b/nbri_ehr/resources/data/nhp_training_result.tsv @@ -0,0 +1,4 @@ +value +In-Progress +Successful +Unsuccessful \ No newline at end of file diff --git a/nbri_ehr/resources/data/nhp_training_type.tsv b/nbri_ehr/resources/data/nhp_training_type.tsv new file mode 100644 index 0000000..4398c3a --- /dev/null +++ b/nbri_ehr/resources/data/nhp_training_type.tsv @@ -0,0 +1,5 @@ +value +Chair +Present +Physical Therapy +Other \ No newline at end of file diff --git a/nbri_ehr/resources/data/normal_abnormal.tsv b/nbri_ehr/resources/data/normal_abnormal.tsv new file mode 100644 index 0000000..951bfe9 --- /dev/null +++ b/nbri_ehr/resources/data/normal_abnormal.tsv @@ -0,0 +1,4 @@ +state +Normal +Abnormal +Not Evaluated \ No newline at end of file diff --git a/nbri_ehr/resources/data/normal_abnormal_only.tsv b/nbri_ehr/resources/data/normal_abnormal_only.tsv new file mode 100644 index 0000000..1ea2e59 --- /dev/null +++ b/nbri_ehr/resources/data/normal_abnormal_only.tsv @@ -0,0 +1,3 @@ +value sort_order +Normal 1 +Abnormal 2 \ No newline at end of file diff --git a/nbri_ehr/resources/data/numeric_unit.tsv b/nbri_ehr/resources/data/numeric_unit.tsv new file mode 100644 index 0000000..909173d --- /dev/null +++ b/nbri_ehr/resources/data/numeric_unit.tsv @@ -0,0 +1,91 @@ +value title description +1 Kg Kilogram +2 mmol Millimole +3 mm Millimeter +4 mL/min Milliliters per minute +5 mL Milliliter +6 mg/L Milligrams per liter +7 mg/g Milligrams per gram +8 mg/dL Milligrams per deciliter +9 mg/d Milligrams per day +10 mg/24 hrs Milligrams per 24 hours +11 mg Milligram +12 mPOL Milli polarization unit +13 mIU/hr Milli international units per hour +14 mIU Milli international units +15 LIV Lyme index value +16 L Liter +17 IU/mL International units per milliliter +18 IU/L International units per liter +19 IU/g International units per gram +20 IU International unit +21 ISR Immune status ratio +22 MPL IgM phospholipid units +23 GPL IgG phospholipid units +24 h Hour +25 g/dL Grams per deciliter +26 g/d Grams per day +27 g/24 hrs Grams per 24 hours +28 g/5 hrs Grams per 5hours +29 g Gram +30 fL Femtoliter +31 EIU Enzyme immunoassay unit +32 EU/mL Ehrlich units per milliliter +33 EU/24 hrs Ehrlich units per 24 hours +34 EU Ehrlich unit +35 ETU/mL Endotoxin units per milliliter +36 dL Deciliter +37 d Day +38 cpy/mL Copies per milliliter +39 CMM Cubic milliliter +40 cP Centipoise unit +41 CFU/mL Colony forming units per milliliter +42 AU/mL Arbitrary units per milliliter +43 U/mL Units per milliliter +44 U/L Units per liter +45 U/hr Units per hour +46 U/g Units per gram +47 U/day Units per day +48 U Unit +49 TV Total volume +50 TIV Toxoplasma index value +51 SD Standard deviation +52 s Second +53 RIV Rubella index value +54 pmol/g Picomoles per gram +55 pmol Picomole +56 pg/mL Picograms per milliliter +57 pg Picogram +58 % Percent +59 ppm Parts per million +60 nmol/mL Nanomoles per milliliter +61 nmol/L Nanomoles per liter +62 nmol/g Nanomoles per gram +63 nmol/dL Nanomoles per deciliter +64 nmol/d Nanomoles per day +65 nmol Nanomole +66 nM/mM Nanomole per millimole +67 ng/mL/hr Nanograms per milliliter per hour +68 ng/mL Nanograms per milliliter +69 ng/L Nanograms per liter +70 ng/dL Nanograms per deciliter +71 ng Nanogram +72 mol Mole +73 min Minute +74 mU/mL Milliunits per milliliter +75 mU/L Milliunits per liter +76 mU/g Milliunits per gram +77 mU Milliunit +78 mOsm/kg Milliosmoles per kilogram +79 mOsm Milliosmole +80 mmol/L Millimoles per liter +81 mmol/d Millimoles per day +82 mmHg Millimeters of Mercury +83 p/m Pulses per minute +84 b/m Breaths per minute +85 hb/m Heartbeats per minute +86 °F Degree Fahrenheit +87 breaths/min Breaths per minute +88 heartbeats/min Heartbeats per minute +89 pulses/min Pulses per minute +90 BCS Body condition score diff --git a/nbri_ehr/resources/data/observation_areas.tsv b/nbri_ehr/resources/data/observation_areas.tsv new file mode 100644 index 0000000..d73b6b2 --- /dev/null +++ b/nbri_ehr/resources/data/observation_areas.tsv @@ -0,0 +1,34 @@ +value title sort_order +N/A N/A 1 +Whole Body Whole Body 2 +Thorax Thorax 4 +EENT EENT 5 +Integ Integ 6 +MS MS 7 +Oral Oral 8 +PLN PLN 9 +U/G U/G 10 +Incision: Main Incision: Main 12 +Incision: Scope Incision: Scope 13 +Incision: L-Port Incision: L-Port 14 +Incision: R-Port Incision: R-Port 15 +Incision: All Incision: All 16 +Right Eyelid Right Eyelid 17 +Left Eyelid Left Eyelid 18 +Left Hand Left Hand 19 +Right Hand Right Hand 20 +Left Foot Left Foot 21 +Right Foot Right Foot 22 +Head & Neck Head & Neck 23 +Right Forelimb Right Forelimb 24 +Left Forelimb Left Forelimb 25 +Chest Chest 26 +Abdomen Abdomen 27 +Upper Back Upper Back 28 +Lower Back Lower Back 29 +Right Upper Leg Right Upper Leg 30 +Left Upper Leg Left Upper Leg 31 +Right Lower Leg & Foot Right Lower Leg & Foot 32 +Left Lower Leg & Foot Left Lower Leg & Foot 33 +Tail Tail 34 +Other Other 35 \ No newline at end of file diff --git a/nbri_ehr/resources/data/observation_types.tsv b/nbri_ehr/resources/data/observation_types.tsv new file mode 100644 index 0000000..b59b7c2 --- /dev/null +++ b/nbri_ehr/resources/data/observation_types.tsv @@ -0,0 +1,55 @@ +value category editorconfig schemaName queryName valueColumn +Abdominal Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"abdominal_obs_types","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups abdominal_obs_types value +Abnormal Behaviors Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"behavior_types","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups behavior_types value +Activity {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"activity","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups activity value +Alopecia Regrowth Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"alopecia_regrowth","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups alopecia_regrowth value +Alopecia Score Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"alopecia_score","forceSelection":true,"displayField":"title","valueField":"value","sortFields":"sort_order"} ehr_lookups alopecia_score value +Alopecia Type Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"alopecia_type","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups alopecia_type value +Appetite {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"app_score","displayField":"value","sortFields":"sort_order","valueField":"value"} ehr_lookups app_score value +Attitude {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"att_score","displayField":"value","valueField":"value"} ehr_lookups att_score value +Auscultation {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"normal_abnormal_only","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups normal_abnormal_only value +Bandage/Splint Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"bandage_observations","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups bandage_observations value +BCS {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"bcs_score","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups bcs_score value +Behavior Abnormality {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"behavior_abnormality","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups behavior_abnormality value +Behavior Management Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"behavior_mgmt_codes","forceSelection":true,"displayField":"title","valueField":"value","sortFields":"sort_order"} ehr_lookups behavior_mgmt_codes value +Capillary Refill Time {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"capillary_refill_time","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups capillary_refill_time value +Daily Enrichment Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"daily_enrich_codes","forceSelection":true,"displayField":"title","valueField":"value","sortFields":"sort_order"} ehr_lookups daily_enrich_codes value +Dental/Oral Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"dental_obs","displayField":"value","sortFields":"sort_order","valueField":"value"} ehr_lookups dental_obs value +Dermatologic Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"derm_obs","displayField":"value","sortFields":"sort_order","valueField":"value"} ehr_lookups derm_obs value +Environmental Change Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"yes_no_order","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups yes_no_order value +Feed Assessment {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"feed_assess_types","displayField":"value","valueField":"value"} ehr_lookups feed_assess_types value +General Behavior Observation Behavior {"xtype":"textfield"} +General Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"general_obs","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups general_obs value +Genitourinary Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"genitourinary_obs","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups genitourinary_obs value +Hernia {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"hernia_types","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups hernia_types value +Hydration {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"hyd_score","displayField":"value","sortFields":"sort_order","valueField":"value"} ehr_lookups hyd_score value +Incision Status {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"incision_score","displayField":"value","sortFields":"sort_order","valueField":"value"} ehr_lookups incision_score value +Lameness {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"lameness","displayField":"value","valueField":"value"} ehr_lookups lameness value +Mass {"xtype":"textfield"} +Menses {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"mens_score","displayField":"value","sortFields":"sort_order","valueField":"value"} ehr_lookups mens_score value +Mucous Membranes {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"mucous_membranes","displayField":"value","sortFields":"sort_order","valueField":"value"} ehr_lookups mucous_membranes value +Musculoskeletal Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"musculoskeletal_observations","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups musculoskeletal_types value +Neurologic Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"neurologic_observations","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups neurologic_observations value +New Injury Observed Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"yes_no_order","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups yes_no_order value +Obstetric Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"obstetric_observations","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups obstetric_observations value +Ocular Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"ocular_observations","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups ocular_problem value +Other Stereotopy Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"yes_no_order","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups yes_no_order value +Preferences Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"preferences","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups preferences value +Rectal Prolapse {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"rectal_prolapse","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups rectal_prolapse value +Respiratory Observations {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"respiratory_observations","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups respiratory_observations value +Respiratory Rate {"xtype":"textfield"} +Self Biting Observed Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"yes_no_order","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups yes_no_order value +SIB Score Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"sib_score","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups sib_score value +Special Enrichment Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"yes_no_order","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups yes_no_order value +Stool {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"stool_types","displayField":"value","sortFields":"sort_order","valueField":"value"} ehr_lookups stool_types value +Temperament Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"temperament","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups temperament value +Testicular volume-Left "{""xtype"":""ehr-simplecombo"",""schemaName"":""ehr_lookups"",""queryName"":""testicular_volume"",""displayField"":""value"",""valueField"":""value"",""sortFields"":""sort_order""}" ehr_lookups testicular_volume value +Testicular volume-Right "{""xtype"":""ehr-simplecombo"",""schemaName"":""ehr_lookups"",""queryName"":""testicular_volume"",""displayField"":""value"",""valueField"":""value"",""sortFields"":""sort_order""}" ehr_lookups testicular_volume value +Vaginal/Uterine Prolapse {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"vaginal_uterine_prolapse","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups vaginal_uterine_prolapse value +Verified Id? {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"yes_no_order","forceSelection":true,"displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups yes_no_order value +Wound Severity Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"wound_severity","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups wound_severity value +Wound Status Behavior {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"wound_status_behavior","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups wound_status_behavior value +Clinical Wound Status {"xtype":"ehr-simplecombo","schemaName":"ehr_lookups","queryName":"wound_status_clinical","displayField":"value","valueField":"value","sortFields":"sort_order"} ehr_lookups wound_status_clinical value +Annual Physical Exam "{""xtype"":""ehr-simplecombo"",""schemaName"":""ehr_lookups"",""queryName"":""exam_findings"",""displayField"":""value"",""valueField"":""value"",""sortFields"":""sort_order""}" ehr_lookups exam_findings value +Introductory Physical Exam "{""xtype"":""ehr-simplecombo"",""schemaName"":""ehr_lookups"",""queryName"":""exam_findings"",""displayField"":""value"",""valueField"":""value"",""sortFields"":""sort_order""}" ehr_lookups exam_findings value +Preshipment Physical Exam "{""xtype"":""ehr-simplecombo"",""schemaName"":""ehr_lookups"",""queryName"":""exam_findings"",""displayField"":""value"",""valueField"":""value"",""sortFields"":""sort_order""}" ehr_lookups exam_findings value \ No newline at end of file diff --git a/nbri_ehr/resources/data/obstetric_observations.tsv b/nbri_ehr/resources/data/obstetric_observations.tsv new file mode 100644 index 0000000..87fb182 --- /dev/null +++ b/nbri_ehr/resources/data/obstetric_observations.tsv @@ -0,0 +1,9 @@ +value sort_order +Pregnant 1 +No pregnancy detected 2 +Mammary gland abscess/mastitis 3 +Agalactia/low milk production 4 +Dystocia/difficult labor 5 +Retained placenta 6 +No abnormality observed 7 +Other 8 \ No newline at end of file diff --git a/nbri_ehr/resources/data/ocular_observations.tsv b/nbri_ehr/resources/data/ocular_observations.tsv new file mode 100644 index 0000000..41bd460 --- /dev/null +++ b/nbri_ehr/resources/data/ocular_observations.tsv @@ -0,0 +1,8 @@ +value sort_order +Blepharospasm/swollen eyelids 1 +Conjunctivitis 2 +Ocular discharge 3 +Phthisis bulbi (shrunken globe) 4 +Cataract(s) 5 +No ocular abnormality observed 6 +Other ocular abnormality 7 \ No newline at end of file diff --git a/nbri_ehr/resources/data/pairing_formation_types.tsv b/nbri_ehr/resources/data/pairing_formation_types.tsv new file mode 100644 index 0000000..64101aa --- /dev/null +++ b/nbri_ehr/resources/data/pairing_formation_types.tsv @@ -0,0 +1,7 @@ +value +Full Contact Pair +Group Formation +Introduction +Limited Contact Pair +Pair Formation +Other \ No newline at end of file diff --git a/nbri_ehr/resources/data/pairing_goal.tsv b/nbri_ehr/resources/data/pairing_goal.tsv new file mode 100644 index 0000000..0aa0edd --- /dev/null +++ b/nbri_ehr/resources/data/pairing_goal.tsv @@ -0,0 +1,5 @@ +value +Solid barrier +Mesh barrier +Full access +Clear barrier \ No newline at end of file diff --git a/nbri_ehr/resources/data/pairing_observation.tsv b/nbri_ehr/resources/data/pairing_observation.tsv new file mode 100644 index 0000000..796e9f1 --- /dev/null +++ b/nbri_ehr/resources/data/pairing_observation.tsv @@ -0,0 +1,4 @@ +value +Compatibility +Incompatible +Undetermined \ No newline at end of file diff --git a/nbri_ehr/resources/data/pairing_reason.tsv b/nbri_ehr/resources/data/pairing_reason.tsv new file mode 100644 index 0000000..92e62c5 --- /dev/null +++ b/nbri_ehr/resources/data/pairing_reason.tsv @@ -0,0 +1,9 @@ +value +Breeding +Buddy monkey +Predicted compatibility +Protocol +Other +Retirement +Re-pairing +Partner Availability \ No newline at end of file diff --git a/nbri_ehr/resources/data/pairing_separation_reason.tsv b/nbri_ehr/resources/data/pairing_separation_reason.tsv new file mode 100644 index 0000000..5290317 --- /dev/null +++ b/nbri_ehr/resources/data/pairing_separation_reason.tsv @@ -0,0 +1,8 @@ +value +Aggression +Sale +Move to social group +Clinical +Relocation +Other +None \ No newline at end of file diff --git a/nbri_ehr/resources/data/preferences.tsv b/nbri_ehr/resources/data/preferences.tsv new file mode 100644 index 0000000..ceff4a8 --- /dev/null +++ b/nbri_ehr/resources/data/preferences.tsv @@ -0,0 +1,4 @@ +Value Title Category Description Sort Order Date Disabled +Foods +Housing and Caging +Social Setting \ No newline at end of file diff --git a/nbri_ehr/resources/data/pregnancy_result.tsv b/nbri_ehr/resources/data/pregnancy_result.tsv new file mode 100644 index 0000000..1c615bc --- /dev/null +++ b/nbri_ehr/resources/data/pregnancy_result.tsv @@ -0,0 +1,3 @@ +value title +1 Stillborn +2 Abort \ No newline at end of file diff --git a/nbri_ehr/resources/data/problem_list_category.tsv b/nbri_ehr/resources/data/problem_list_category.tsv new file mode 100644 index 0000000..67fcf34 --- /dev/null +++ b/nbri_ehr/resources/data/problem_list_category.tsv @@ -0,0 +1,14 @@ +value description +Behavioral Behavioral issue or concern. Examples include SIB and fecal smearing. +Trauma Case opened for some type of trauma. +GI abnormality Abnormalities associated with the digestive system. +Neurologic abnormality Abnormalities associated with the neurologic system. +Dermatologic abnormality Abnormalities associated with the dermal system. +Genitourinary abnormality Abnormalities associated with the genitourinary system. +Circulatory abnormality Abnormalities associated with the circulatory system. +Ocular abnormality Abnormalities associated with the ocular system. +Respiratory abnormality Abnormalities associated with the respiratory system. +Oral abnormality Abnormalities associated with the oral cavity. +Musculoskeletal abnormality Abnormalities associated with the musculoskeletal system. +General abnormality Abnormalities that do not fit into any other category. +Study-related surgery Case opened for a surgery or activity supporting a research project. \ No newline at end of file diff --git a/nbri_ehr/resources/data/problem_list_subcategory.tsv b/nbri_ehr/resources/data/problem_list_subcategory.tsv new file mode 100644 index 0000000..fae2d42 --- /dev/null +++ b/nbri_ehr/resources/data/problem_list_subcategory.tsv @@ -0,0 +1,75 @@ +value category +Alopecia Behavioral +SIB Behavioral +Other behavioral Behavioral +Stereotypy Behavioral +Fecal smear Behavioral +Eye poking Behavioral +Urine drinking Behavioral +Copraphagy Behavioral +Skin laceration(s) Trauma +Muscle laceration(s) Trauma +Crushing wounds Trauma +Abrasions Trauma +Fracture(s) Trauma +Puncture wounds Trauma +Traumatic amputation(s) Trauma +SIB (self-injurious behavior) Trauma +Other trauma Trauma +Diarrhea GI abnormality +Undercondition General abnormality +Dehydration General abnormality +Bloody Stool GI abnormality +Anorexia GI abnormality +Rectal prolapse GI abnormality +Hepatomegaly GI abnormality +Other GI abnormality GI abnormality +Ataxia Neurologic abnormality +Paralysis/Paresis Neurologic abnormality +Head tilt Neurologic abnormality +Other neurologic abnormality Neurologic abnormality +Penile/preputial lesions Dermatologic abnormality +Dermatitis Dermatologic abnormality +Abscess Dermatologic abnormality +Incisional infection Dermatologic abnormality +Skin mass Dermatologic abnormality +Skin lesion(s) Dermatologic abnormality +Other dermatologic abnormality Dermatologic abnormality +Dystocia Genitourinary abnormality +Vaginal prolapse Genitourinary abnormality +Uterine enlargement Genitourinary abnormality +Endometriosis Genitourinary abnormality +Retained placenta Genitourinary abnormality +Hematuria (bloody urine) Genitourinary abnormality +Other genitourinary abnormality Genitourinary abnormality +AV fistula Circulatory abnormality +Heart murmur Circulatory abnormality +Other circulatory abnormality Circulatory abnormality +Conjunctivitis/ocular discharge Ocular abnormality +Blepharospasm Ocular abnormality +Corneal ulcer Ocular abnormality +Other ocular abnormality Ocular abnormality +Dyspnea/Labored breathing Respiratory abnormality +Purulent nasal discharge Respiratory abnormality +Epistaxis/bloody nasal discharge Respiratory abnormality +Other respiratory abnormality Respiratory abnormality +Tooth abscess Oral abnormality +Gingivitis/periodontal disease Oral abnormality +Foreign body in cheek pouch Oral abnormality +Oral mass Oral abnormality +Other oral abnormality Oral abnormality +Lameness Musculoskeletal abnormality +Other musculoskeletal abnormality Musculoskeletal abnormality +Weight loss General abnormality +Edema General abnormality +Abdominal mass General abnormality +Unresponsive/Down General abnormality +Lethargy General abnormality +Orphan/dam neglect General abnormality +Anemia General abnormality +Thrombocytopenia General abnormality +Other general abnormality General abnormality +Jejunal resection Study-related surgery +Liver biopsy Study-related surgery +Spleen biopsy Study-related surgery +Other study-related surgery Study-related surgery diff --git a/nbri_ehr/resources/data/procedure_category.tsv b/nbri_ehr/resources/data/procedure_category.tsv new file mode 100644 index 0000000..6a78807 --- /dev/null +++ b/nbri_ehr/resources/data/procedure_category.tsv @@ -0,0 +1,5 @@ +Value Title Category Description Sort Order Date Disabled +Pathology Pathology 4 +Procedure Procedure 1 +Research Research 3 +Surgery Surgery 2 \ No newline at end of file diff --git a/nbri_ehr/resources/data/procedures.tsv b/nbri_ehr/resources/data/procedures.tsv new file mode 100644 index 0000000..4560d70 --- /dev/null +++ b/nbri_ehr/resources/data/procedures.tsv @@ -0,0 +1,130 @@ +Name +Oral Dose Administration +Oral Dose Administration - Alert +Oral Dose Administration - Intubation +Sublingual Dose Administration +Intrarectal Dose Administration +Intramuscular Dose Administration +IM Dose Administration - Quadriceps +IM Dose Administration - Deltoid +Subcutaneous Dose Administration +Intravenous Dose Administration +Intravenous Dose Administration - Bolus +Intravenous Dose Admin - Infusion +Intraperitoneal Dose Administration +Topical Dose Administration +Inhalation Dose Administration +Intranasal Dose Administration +Intravaginal Dose Administration +Body Weight +Electrocardiogram +Temperature Monitoring +Heart Rate Monitoring +Blood Pressure Monitoring +WelshAllyn Vital Signs Montoring +Respiration Monitoring +Pulse Rate Monitoring +Sedative Administration +Ketamine Administration +Diazepam Administration +Telazol Administration +Xylazine Administration +Ketamine/Diazepam Administration +Ketamine/Xylazine Administration +Intramuscular Anesthesia +Venipuncture +Blood Collection +Blood Collection - SST for serum +Blood Collection - EDTA for plasma +BC - Sodium Heparin for plasma +Blood Collection - EDTA for PBMCs +BC - Sodium Heparin for PBMCs +Blood Collection - EDTA for Flow +Blood Collection - EDTA for CBC +Blood Collection - SST for Chemistry +B C - Sodium Citrate for Coag +B C - Sodium Citrate for plasma +Urine Collection +Urine Collection - Catheter +Urine Collection - Pan catch +Cervicovaginal Secretion Collection +Stool Collection +Rectal Swab Sample Collection +Nasal Wash Sample Collection +Saliva Sample Collection +Wound Specimen Collection +Tissue Collection +Tissue Collection - Necropsy +Bleeding Time Test +Radiography +Tuberculosis Skin Test +Intradermal Skin Test +Pole and Collar +Squeeze Cage +Primate Chair +Chemical Restraint +Hand Catch +Daily Observations +Apheresis +Endoscopy Assistance +Ultrasound Assistance +Lymph Node Biopsy +Liver Biopsy +Skin Biopsy +Behavioral Observations +Continuous Observations +30 - minute Observations +SID Observations +BID Observations +Interval Observations (IST) +Intravenous Anesthesia +BC - Sodium Citrate for Coag +BC - Sodium Citrate for plasma +Follow-up Physical Exam +Prestudy Physical Exam +Ophthalmic Exam - Direct +Ophthalmic Exam - Indirect +Oophorectomy +Wedge Liver Biopsy +Skin Boipsy +Liver Percutaneous Biopsy +Hepatic Biopsy - Tru Cut +Hepatic Biopsy - Menghini Technique +Skeletal Muscle Biopsy +Lung Biopsy +White fat Biopsy +Brown fat Biopsy +Renal Biopsy +Gastric Biopsy +Intestinal Biopsy +Cervical Biopsy +Rectal Biopsy +Urine Biopsy +Vaginal Biopsy +Testicular Biopsy +Bone Marrow Biopsy +Bone Marrow Aspirates +Splenectomy +Thoracocentesis +Abdominocentesis +Catheter/Canula Placement - Femoral +Catheter/Canula Placement - Saphenous +Cather/Canula Placement - Intestinal +Catheter/Canula Placement - Portal +Aspirate - Specify +Abdominal Ultrasound +Cardiac Ultrasound +Thoracic Ultrasound +Ultrasound - Specify +Skin-Biopsy +Embryo Transfer +Oocyte Collection +Electroejaculation +Cesarian section +Vasectomy +Pulpectomy +Pulpotomy +wfrfr3 +Thoracocentesiss +BC - Sodium Citrate for Coags +BC - Sodium Citrate for plasmas \ No newline at end of file diff --git a/nbri_ehr/resources/data/protocol_category.tsv b/nbri_ehr/resources/data/protocol_category.tsv new file mode 100644 index 0000000..6fb50d6 --- /dev/null +++ b/nbri_ehr/resources/data/protocol_category.tsv @@ -0,0 +1,3 @@ +value title +1 Stock/Breeder Protocol +2 Study Protocol \ No newline at end of file diff --git a/nbri_ehr/resources/data/protocol_state.tsv b/nbri_ehr/resources/data/protocol_state.tsv new file mode 100644 index 0000000..1420c93 --- /dev/null +++ b/nbri_ehr/resources/data/protocol_state.tsv @@ -0,0 +1,7 @@ +value title +0 Template +1 Unsubmitted +2 Submitted +3 Approved +4 Not Approved +5 Returned \ No newline at end of file diff --git a/nbri_ehr/resources/data/protocol_type.tsv b/nbri_ehr/resources/data/protocol_type.tsv new file mode 100644 index 0000000..2b0eb13 --- /dev/null +++ b/nbri_ehr/resources/data/protocol_type.tsv @@ -0,0 +1,6 @@ +value title +0 Template +1 Original +2 Amendment +3 Renewal +4 Renewal/Amendment \ No newline at end of file diff --git a/nbri_ehr/resources/data/qualifier.tsv b/nbri_ehr/resources/data/qualifier.tsv new file mode 100644 index 0000000..19fc27d --- /dev/null +++ b/nbri_ehr/resources/data/qualifier.tsv @@ -0,0 +1,54 @@ +value title description +1 Species Species +2 Sex Sex +3 Age Age +4 Naive Naive +5 No Exposure to MAB No Exposure to MAB +6 No Exposure to other No Exposure to other +7 No Exposure to 30ds No Exposure to 30ds +8 No Exposure to 60ds No Exposure to 60ds +9 No Exposure to 90ds No Exposure to 90ds +10 No exposure for other No exposure for other +11 Juvenile Juvenile +12 HCV negative HCV negative +13 HIV negative HIV negative +14 HBV negative HBV negative +15 Monoclonal negative Monoclonal negative +16 HCV HCV +17 Antigenemia positive Antigenemia positive +18 SPF SPF +19 Enteric pathogen negative Enteric pathogen negative +20 Accepts alert dosing Accepts alert dosing +21 Alert bleeding Alert bleeding +22 Chair trained Chair trained +23 Obesity Obesity +24 Diabetes Diabetes +25 Male Male +26 Female Female +27 Over 2 years old Over 2 years old +28 Oophorectomized Oophorectomized +29 Vasectomy Vasectomy +30 Castration Castration +31 Hysterectomy Hysterectomy +32 Canines blunted Canines blunted +33 Canines removed Canines removed +34 Limb amputation Limb amputation +35 Abdominal Surgery (in the past) Abdominal Surgery (in the past) +36 SIB (under current medication) Self Injurious Behavior (under current medication) +37 Chronic enteritis Chronic enteritis +38 Intermittent recurrent enteritis Intermittent recurrent enteritis +39 No experimental usage for 30days No experimental usage for 30days +40 Splenectomized Splenectomized +41 Partial hepatic lobectomy Partial hepatic lobectomy +42 Chronic disease Chronic disease (may be heart disease, anything other than enteritis or diabetes) +43 Alert bleeding trained Alert bleeding trained +44 Non-pregnant Non-pregnant +45 Lactating Lactating +46 Behavioral stereotypy (other than SIB) Behavioral stereotypy (other than SIB) +47 1 - 2 years old 1 - 2 years old +48 Less than 1 year old Less than 1 year old +49 Nursing infant Nursing infant +50 Pregnant Pregnant +51 No Exposure for 30ds No Exposure for 30ds +52 No Exposure for 60ds No Exposure for 60ds +53 No Exposure for 90ds No Exposure for 90ds diff --git a/nbri_ehr/resources/data/questionnaire.tsv b/nbri_ehr/resources/data/questionnaire.tsv new file mode 100644 index 0000000..08e8bad --- /dev/null +++ b/nbri_ehr/resources/data/questionnaire.tsv @@ -0,0 +1,4 @@ +value title +1 Short, ver 1 +3 Short, ver 2 +4 Complete, ver 1 \ No newline at end of file diff --git a/nbri_ehr/resources/data/rectal_prolapse.tsv b/nbri_ehr/resources/data/rectal_prolapse.tsv new file mode 100644 index 0000000..98f995c --- /dev/null +++ b/nbri_ehr/resources/data/rectal_prolapse.tsv @@ -0,0 +1,3 @@ +value sort_order +Present 1 +Not present 2 \ No newline at end of file diff --git a/nbri_ehr/resources/data/regulatory_stress_levels.tsv b/nbri_ehr/resources/data/regulatory_stress_levels.tsv new file mode 100644 index 0000000..40aed55 --- /dev/null +++ b/nbri_ehr/resources/data/regulatory_stress_levels.tsv @@ -0,0 +1,6 @@ +value title description +1 A USDA Stress Level A +2 B USDA Stress Level B +3 C USDA Stress Level C +4 D USDA Stress Level D +5 E USDA Stress Level E diff --git a/nbri_ehr/resources/data/req_order_state.tsv b/nbri_ehr/resources/data/req_order_state.tsv new file mode 100644 index 0000000..a30594d --- /dev/null +++ b/nbri_ehr/resources/data/req_order_state.tsv @@ -0,0 +1,6 @@ +value title +0 Template +1 In Progress +2 Submitted +4 Not Approved +5 Approved \ No newline at end of file diff --git a/nbri_ehr/resources/data/req_order_type.tsv b/nbri_ehr/resources/data/req_order_type.tsv new file mode 100644 index 0000000..1dd7d05 --- /dev/null +++ b/nbri_ehr/resources/data/req_order_type.tsv @@ -0,0 +1,5 @@ +value title +1 Single +2 Standing +3 Waiting List +4 Back \ No newline at end of file diff --git a/nbri_ehr/resources/data/respiratory_observations.tsv b/nbri_ehr/resources/data/respiratory_observations.tsv new file mode 100644 index 0000000..fdc5574 --- /dev/null +++ b/nbri_ehr/resources/data/respiratory_observations.tsv @@ -0,0 +1,9 @@ +value sort_order +Tachypnea (increased respiratory rate) 1 +Dyspnea (difficulty breathing) 2 +Epistaxis (bloody nasal discharge) 3 +Clear nasal discharge 4 +Purulent nasal discharge 5 +Wheezing or noisy breathing 6 +No respiratory abnormality observed 7 +Other respiratory abnormality 8 \ No newline at end of file diff --git a/nbri_ehr/resources/data/routes.tsv b/nbri_ehr/resources/data/routes.tsv new file mode 100644 index 0000000..8d83daf --- /dev/null +++ b/nbri_ehr/resources/data/routes.tsv @@ -0,0 +1,17 @@ +Route Meaning +IM +intracardiac +intracarotid +intracorneal Intracorneal +intracranial +IP intraperitoneal +IT +IV +IVAG +oral +PO +rectal +SQ +topical +topical (eye) +topical (skin) diff --git a/nbri_ehr/resources/data/sib_score.tsv b/nbri_ehr/resources/data/sib_score.tsv new file mode 100644 index 0000000..5998060 --- /dev/null +++ b/nbri_ehr/resources/data/sib_score.tsv @@ -0,0 +1,8 @@ +value sort_order +0 1 +1.1 2 +1.2 3 +1.3 4 +1 4 +2 5 +3 6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/snomed.tsv b/nbri_ehr/resources/data/snomed.tsv new file mode 100644 index 0000000..9253d5d --- /dev/null +++ b/nbri_ehr/resources/data/snomed.tsv @@ -0,0 +1,357 @@ +Code Meaning +NBRI-001 Acepromazine +NBRI-002 Acetaminophen +NBRI-003 Adequan +NBRI-004 Albendazole +NBRI-005 Albon suspension +NBRI-006 Albuterol +NBRI-007 Alfaxalone +NBRI-008 Alfentanil +NBRI-009 Alprazolam +NBRI-010 Aluminum Hydroxide +NBRI-011 Amikacin Sulfate +NBRI-012 Aminophylline +NBRI-013 Amiodarone +NBRI-014 Amitriptyline +NBRI-015 Amoxicillin +NBRI-016 Amoxicillin / Clavulanic Acid +NBRI-017 Amoxi-Mast +NBRI-018 Ampicillin +NBRI-019 Ampicillin/Sulbactam +NBRI-020 Artemether +NBRI-021 Aspirin +NBRI-022 Atenolol Suspension +NBRI-023 Atipamezole HCl +NBRI-024 Atracurium +NBRI-025 Atropine Sulfate +NBRI-026 Azathioprine +NBRI-027 Azithromycin +NBRI-028 Barium Sulfate +NBRI-029 Belatacept +NBRI-030 Benzoyl Peroxide Shampoo +NBRI-031 Betamethasone Dipropionate +NBRI-032 Bethanechol +NBRI-033 Bio-Sponge +NBRI-034 Biozide Gel +NBRI-035 Bismuth Subsalicylate +NBRI-036 Budesonide +NBRI-037 Bupivacaine HCl +NBRI-038 Bupivacaine HCl And Epinephrine +NBRI-039 Bupivacaine SR (Nocita) +NBRI-040 Buprenorphine +NBRI-041 Buprenorphine SR +NBRI-042 Busulfan +NBRI-043 Butorphanol Tartrate +NBRI-044 Calcium citrate powder +NBRI-045 Calcium gluconate 23% +NBRI-046 Carprofen, injectable +NBRI-047 Carprofen, oral +NBRI-048 Carvedilol +NBRI-049 Cd3-Immunotoxin +NBRI-050 Cefazolin +NBRI-051 Cefdinir +NBRI-052 Cefovecin (Convenia) +NBRI-053 Cefpodoxime +NBRI-054 Ceftiofur crystalline free acid (CFFA) +NBRI-055 Ceftriaxone +NBRI-056 Cefuroxime +NBRI-057 Cephalexin +NBRI-058 Chloramphenicol +NBRI-059 Chlorhexidine spray (Duoxo®) +NBRI-060 Chloroquine +NBRI-061 Chlorpromazine +NBRI-062 Chlorthalidone +NBRI-063 Cimetidine +NBRI-064 Ciprofloxacin +NBRI-065 Cisapride +NBRI-066 Clay +NBRI-067 Clindamycin +NBRI-068 Clobetasol Propionate +NBRI-069 Clomipramine +NBRI-070 Clopidogrel +NBRI-071 Cloprostenol +NBRI-072 Colchicine +NBRI-073 Collodial Oatmeal +NBRI-074 Cyanocobalamin (Vitamin B12) +NBRI-075 Cyclomydril +NBRI-076 Cyclophosphamide +NBRI-077 Cyclosporine +NBRI-078 Cyproheptadine +NBRI-079 DA2PP Vaccine (Distemper, Adenovirus Type 2, Parvovirus, Parainfluenza) +NBRI-080 Definity +NBRI-081 Denv Vaccine +NBRI-082 Derma Caps +NBRI-083 Deslorelin +NBRI-084 Dexamethasone +NBRI-085 Dexamethasone SP +NBRI-086 Dexmedetomidine HCl +NBRI-087 Dextromethorphan +NBRI-088 Dextrose +NBRI-089 Diazepam +NBRI-090 Diclofenac Sodium Ophthalmic Solution +NBRI-091 Diet, Ensure Liquid Nutrition +NBRI-092 Diet, Ensure Soaked Biscuits +NBRI-093 Diet, Juice Soaked Biscuits +NBRI-094 Diet, Misc, Nos +NBRI-095 Diet, Water Soaked Biscuits +NBRI-096 Digoxin +NBRI-097 Dimethicone Barrier Cream +NBRI-098 Dinoprost (PGF2 alpha) +NBRI-099 Diphenhydramine, injectable +NBRI-100 Diphenhydramine, oral +NBRI-101 Diphenoxylate +NBRI-102 Dobutamine +NBRI-103 Docusate Sodium +NBRI-104 Dopamine +NBRI-105 Doxapram +NBRI-106 Doxipen +NBRI-107 Doxycycline +NBRI-108 Draxxin +NBRI-109 Dronabinol +NBRI-110 Drug, Nos +NBRI-111 Ear cleaning solution +NBRI-112 Enalapril +NBRI-113 Enrofloxacin, injectable +NBRI-114 Enrofloxacin, oral +NBRI-115 Enulose +NBRI-116 Epinephrine [1:1000, 1 mg/mL] +NBRI-117 Epoetin +NBRI-118 Epsom salt bag +NBRI-119 Erythromycin +NBRI-120 Essential 6 Spot On +NBRI-121 Famotidine, injectable +NBRI-122 Famotidine, oral +NBRI-123 Fenbendazole +NBRI-124 Fentanyl +NBRI-125 Fenugreek +NBRI-126 Finasteride +NBRI-127 Florfenicol +NBRI-128 Fluconazole +NBRI-129 Flumazenil +NBRI-130 Flunixin meglumine +NBRI-131 Fluoxetine +NBRI-132 Flurbiprofen +NBRI-133 Fosphenytoin +NBRI-134 FSH +NBRI-135 Furosemide +NBRI-136 FVRCP vaccine (Feline Viral Rhinotracheitis, Calicivirus, Panleukopenia) +NBRI-137 Gabapentin +NBRI-138 Gentamicin +NBRI-139 Gentamicin/ betamethasone spray +NBRI-140 Glipizide +NBRI-141 Glucosamine/Chondroitin Ds +NBRI-142 Glucosamine/Chondroitin/Msm +NBRI-143 Glycopyrrolate +NBRI-144 Golytely +NBRI-145 Granulex +NBRI-146 Griseofulvin +NBRI-147 Guanfacine +NBRI-148 Haloperidol decanoate (depot) +NBRI-149 Haloperidol lactate +NBRI-150 Heparin Sodium +NBRI-151 Hetastarch +NBRI-152 Human Chorionic Gonadotropin +NBRI-153 Humilac +NBRI-154 Hydrocortisone cream +NBRI-155 Hydrogel +NBRI-156 Hydromorphone +NBRI-157 Hydromorphone Injectable Hcl +NBRI-158 Hypertonic Saline +NBRI-159 Ibuprofen +NBRI-160 Indocyanine Green +NBRI-161 Influenza Vaccine +NBRI-162 Insulin +NBRI-163 Insulin (rapid, short, and intermediate acting) +NBRI-164 Insulin, Degludec +NBRI-165 Insulin, Glargine +NBRI-166 Iodoquinolol +NBRI-167 Iohexol (Omnipaque) +NBRI-168 Iron Dextran +NBRI-169 Isoflurane +NBRI-170 Isoniazid +NBRI-171 Isoproterenol +NBRI-172 Isovue-300 +NBRI-173 Isovue-370. T +NBRI-174 Itraconazole +NBRI-175 Ivermectin 1% Injectable +NBRI-176 Kaolin & Pectin +NBRI-177 Karo syrup +NBRI-178 Ketaloric Trimethamine Ophthalmic Solution +NBRI-179 Ketamine Injectable +NBRI-180 Ketoconazole +NBRI-181 Ketoprofen Injectable +NBRI-182 Ketorolac +NBRI-183 Lactated ringers solution +NBRI-184 Leuprolide +NBRI-185 Levetiracetam +NBRI-186 Lidocaine + epinephrine +NBRI-187 Lidocaine Hydrochloride +NBRI-188 Loperamide Hydrochloride +NBRI-189 Loratadine +NBRI-190 Lorazepam +NBRI-191 L-Tryptophan +NBRI-192 L-Lysine +NBRI-193 Magnesium hydroxide +NBRI-194 Mannitol +NBRI-195 Maropitant Citrate +NBRI-196 Mct Oil +NBRI-197 Measles, Mumps, Rubella Vaccine (MMR) +NBRI-198 Mebendazole +NBRI-199 Medetomidine Hcl +NBRI-200 Medihoney +NBRI-201 Medroxyprogesterone acetate (Depo-Provera) +NBRI-202 Mefloquine +NBRI-203 Megestrol Acetate +NBRI-204 Melengestrol Acetate +NBRI-205 Meloxicam, injectable +NBRI-206 Meloxicam, oral +NBRI-207 Meloxicam, sustained release +NBRI-208 Menotropins +NBRI-209 Mesalamine +NBRI-210 Metamucil Powder +NBRI-211 Metformin +NBRI-212 Methotrexate +NBRI-213 Methylene Blue +NBRI-214 Methylprednisolone acetate (Depo-Medrol) +NBRI-215 Methylprednisolone sodium succinate (Solu-medrol) +NBRI-216 Metoclopramide +NBRI-217 Metronidazole, injectable +NBRI-218 Metronidazole, oral +NBRI-219 Miconahex + Triz +NBRI-220 Midazolam +NBRI-221 Mifepristone +NBRI-222 Minocycline HCl +NBRI-223 Mirtazapine +NBRI-224 Misoprostol +NBRI-225 Morphine +NBRI-226 Moxidectin +NBRI-227 Moxifloxacin Opthalmic +NBRI-228 Multivitamin Preparation, Nos +NBRI-229 Mylanta +NBRI-230 Nalbuphine +NBRI-231 Naloxone +NBRI-232 Naltrexone +NBRI-233 Nembutal +NBRI-234 Neo/Poly/Bac W/Dexamethasone +NBRI-235 Neomycin Sulfate +NBRI-236 Neomycin/Bacitracin/Polymyxin +NBRI-237 Neostigmine +NBRI-238 Nitazoxanide +NBRI-239 Normasol +NBRI-240 Nystatin +NBRI-241 N-acetylcysteine +NBRI-242 Olanzapine +NBRI-243 Omeprazole +NBRI-244 Ondansetron +NBRI-245 Ophthalmic Eye Wash +NBRI-246 Oral rehydration salts (oral electrolytes) +NBRI-247 Oxacillin +NBRI-248 Oxycodone Hydrochloride +NBRI-249 Oxygen +NBRI-250 Oxymorphone Hydrochloride +NBRI-251 Oxytetracycline +NBRI-252 Oxytocin +NBRI-253 Packed red blood cells +NBRI-254 Pancuronium +NBRI-255 Pantoprazole (Protonix) +NBRI-256 Paromomycin +NBRI-257 Penicillin G Procaine +NBRI-258 Pentobarbital (euthanasia solution) +NBRI-259 Pentobarbitol Sodium +NBRI-260 Phenazopyridine +NBRI-261 Phenobarbital +NBRI-262 Phenylephrine +NBRI-263 Phenytoin +NBRI-264 Phytonadione (Vitamin K1) +NBRI-265 Pimobendan +NBRI-266 Pioglitazone +NBRI-267 Plasma +NBRI-268 Platelet rich plasma (PRP) +NBRI-269 Polymyxin B +NBRI-270 Polymyxin B Sulfate and Bacitracin ophthalmic ointment +NBRI-271 Potassium chloride 10%, injectable +NBRI-272 Potassium Gluconate +NBRI-273 Potassium, oral +NBRI-274 Prang +NBRI-275 Praziquantel +NBRI-276 Prazosin +NBRI-277 Prednisolone +NBRI-278 Prednisolone Sodium Succinate +NBRI-279 Prednisone +NBRI-280 Primaquine +NBRI-281 Probiotic, B. Infantis +NBRI-282 Probiotic, Capsule +NBRI-283 Probiotic, L. Reuteri +NBRI-284 Probiotic, Paste +NBRI-285 Probiotic, Visbiome +NBRI-286 Prochlorperazine +NBRI-287 Propofol +NBRI-288 Propranolol +NBRI-289 Psyllium Seed +NBRI-290 Putrescine +NBRI-291 Pyrantel pamoate +NBRI-292 Quinine +NBRI-293 Rabies Vaccine, Killed Virus, 1 year +NBRI-294 Rabies Vaccine, Killed Virus, 3 year +NBRI-295 Rabies Vaccine, Modified Live Virus +NBRI-296 Ranitidine +NBRI-297 Rapamycin +NBRI-298 Robenacoxib (Onsior) +NBRI-299 Rocuronium Bromide +NBRI-300 Ropivacaine +NBRI-301 S-adenosyl-L-methionine (SAMe) + milk thistle extract +NBRI-302 Sevoflurane +NBRI-303 Shampoo, Chlorhexidine +NBRI-304 Shampoo, Epi-Soothe +NBRI-305 Shampoo, medicated other +NBRI-306 Silver sulfadiazine (SSD) Cream +NBRI-307 Simethicone +NBRI-308 Sodium Bicarbonate +NBRI-309 Sodium Chloride +NBRI-310 Spironolactone +NBRI-311 Succinylcholine +NBRI-312 Sucralfate +NBRI-313 Sufentanil +NBRI-314 Sulfadimethoxine +NBRI-315 Sulfamethoxazole/Trimethoprim +NBRI-316 Sulfasalazine +NBRI-317 Tacrolimus +NBRI-318 Terbutaline +NBRI-319 Terbutaline Sulfate Injectable +NBRI-320 Tetanus Toxoid Vaccine +NBRI-321 Tetracaine ophthalmic solution +NBRI-322 Tetracycline +NBRI-323 Theophylline +NBRI-324 Thiabendazole +NBRI-325 Tiletamine/Zolazepam Injectable (Telazol) +NBRI-326 Tinidazole +NBRI-327 Tobramycin Opthalmic +NBRI-328 Tramadol +NBRI-329 Tranexamic acid (TEA) +NBRI-330 Trazadone +NBRI-331 Triamcinilone Acetate +NBRI-332 Trimethoprim/Sulfa +NBRI-333 Triple Antibiotic Ointment +NBRI-334 Tryptophan +NBRI-335 Tuberculin mammalian +NBRI-336 Tulathromycin +NBRI-337 Tylan Injectable +NBRI-338 Tylosin +NBRI-339 Ursodiol +NBRI-340 Valbazen +NBRI-341 Valganciclovir Hydrochloride +NBRI-342 Vancomycin +NBRI-343 Vanguard DM (Distemper-Measles vaccine) +NBRI-344 Vecuronium +NBRI-345 Venlafaxine +NBRI-346 Vetericyn Plus Spray +NBRI-347 Vitamin B Complex +NBRI-348 Vitamin C +NBRI-349 Vitamin D3 +NBRI-350 Vitamin K1 +NBRI-351 Water Soaked Chow +NBRI-352 Whole blood +NBRI-353 Xylazine Injectable +NBRI-354 Yohimbine +NBRI-355 Zenpep +NBRI-35p Post-Op Rounds \ No newline at end of file diff --git a/nbri_ehr/resources/data/source.tsv b/nbri_ehr/resources/data/source.tsv new file mode 100644 index 0000000..0d893c4 --- /dev/null +++ b/nbri_ehr/resources/data/source.tsv @@ -0,0 +1,108 @@ +code meaning +1 Adv Bioscience Labs +2 Alamogordo PrimateFaclty +3 Alpha Genesis, Inc. +4 Barton West End Farm +5 Battelle Memorial Inst +6 Baylor Research Inst +7 BIOCULTURE (MTIUS) LTD +8 Bioculture US LLC +9 BIOQUAL, Inc. +10 Boehringer Ingelheim +11 Boston University +12 Buckshire Corporation +13 Caribbean Primate Rsrch +14 CBNC +15 CDC +16 Charles River Laboratory +17 Charles River/Reno +18 Chimp Haven +19 China/Guangxi GF Sci Pri +20 Chiron Corp +21 CiToxLab North America +22 Covance Research Prod +23 CR Rsrch Models Houston +24 Ctr Captive Chimp Care +25 Cynologics Ltd +26 DHMRI +27 Duke Univ Medical Ctr +28 Durham Research Center +29 Emory University YPRC +30 Envigo Global Services +31 Guangdong Landau Biotech +32 Hainan, China +33 Harvard Medical School +34 Indonesia (Pt. W. Sat) +35 Johns Hopkins University +36 LC Preclinical Research +37 Lovelace Biomedical +38 LRRI +39 LSU Health Science BR +40 LSU Health Science NO +41 LSU Health Science Shv +42 Mannheimer Foundation +43 Mass. General Hospital +44 MD Anderson Cancer Ctr. +45 Merck & Co (Rahway) +46 Merck & Co (WP) +47 Merck Research Labs WP +48 Nationwide Children's +49 New England NPRC +50 New York University +51 NIAID (Bioqual) +52 NIAID Morgan Island +53 NIAID NIH Animal Ctr +54 NICHD/NIH +55 NIH +56 NIH Animal Center +57 NINDS NIH Animal Ctr +58 Novartis Pharm. Corp. +59 Novartis Vaccines Srl +60 NYU School of Medicine +61 Oregon NPRC +62 Pfizer +63 Pfizer-Andover +64 Pfizer-Pearl River +65 PreLabs +66 Primate Products +67 Primedica Labs +68 PrimGen +69 Primgen CSP +70 RainForest Adventures +71 Republic of Mauritius +72 Rocky Mountain Lab +73 Save the Chimps +74 Siconbrec Inc +75 Sierra Biomedical +76 SNBL-SRC +77 SRI International +78 St. Jude Childrens Rsrch +79 St. Kitts +80 Stanford Univ School Med +81 Stony Brook University +82 SUNY Downstate Medical +83 SW Found Biomed Rsrch +84 Texas Biomed +85 Three Springs Scientific +86 Tulane NPC (Covington) +87 Tulane Univ Medical Ctr +88 Univ Alabama Birmingham +89 Univ of Illinois +90 Univ of Kansas Med Ctr +91 Univ of Maryland +92 Univ of Nebraska Med Ctr +93 Univ of Pittsburgh +94 Univ of Texas at Austin +95 Univ of Washington NPRC +96 Univ of Wisconsin +97 Univ Tex MD Anderson CC +98 USAMRICD +99 USAMRIID +100 Virginia Commonwealth U +101 WakeForest School of Med +102 WaNPRC +103 Worldwide Primates, Inc. +104 WRAIR +105 Wyeth-Ayerst Rsrch (PR) +106 Yale Univ Sch Medicine +107 Yerkes Regional PRC \ No newline at end of file diff --git a/nbri_ehr/resources/data/species.tsv b/nbri_ehr/resources/data/species.tsv new file mode 100644 index 0000000..c95e4bd --- /dev/null +++ b/nbri_ehr/resources/data/species.tsv @@ -0,0 +1,7 @@ +Common Scientific Name Id Prefix Mhc Prefix Max Blood Draw (mL/kg) Max Percent Blood Drawn Blood Reconstitution Interval (Days) Cites Code Date Disabled USDA Gestation +African Green Monkey Chlorocebus aethiops AGM 3.0000 1.0000 7.0000 +Brown-Tufted Capuchin Cebus apella CAP 3.0000 1.0000 7.0000 +Cynomolgus Macaque Macaca fascicularis CYN 3.0000 1.0000 7.0000 +Marmoset 3.0000 1.0000 7.0000 +Pig-Tailed Macaque Macaca nemestrina PIG 3.0000 1.0000 7.0000 +Rhesus Macaque Macaca mulatta RHM 3.0000 1.0000 7.0000 \ No newline at end of file diff --git a/nbri_ehr/resources/data/species_codes.tsv b/nbri_ehr/resources/data/species_codes.tsv new file mode 100644 index 0000000..df698e7 --- /dev/null +++ b/nbri_ehr/resources/data/species_codes.tsv @@ -0,0 +1,7 @@ +Code Scientific Name Common Name Description Genus Species Date Disabled +1 Chlorocebus aethiops AGM African Green Monkey 3 +10 Macaca mulatta RHM Rhesus Macaque 3 +18 Marmoset 3 +4 Cebus apella CAP Brown-Tufted Capuchin 3 +7 Macaca fascicularis CYN Cynomolgus Macaque 3 +9 Macaca nemestrina PIG Pig-Tailed Macaque 3 \ No newline at end of file diff --git a/nbri_ehr/resources/data/stool_score.tsv b/nbri_ehr/resources/data/stool_score.tsv new file mode 100644 index 0000000..121feeb --- /dev/null +++ b/nbri_ehr/resources/data/stool_score.tsv @@ -0,0 +1,7 @@ +value sort_order +F 1 +F/M 2 +F/M/L 3 +M 4 +M/F 4 +M/F/L 5 \ No newline at end of file diff --git a/nbri_ehr/resources/data/stool_types.tsv b/nbri_ehr/resources/data/stool_types.tsv new file mode 100644 index 0000000..79aeb54 --- /dev/null +++ b/nbri_ehr/resources/data/stool_types.tsv @@ -0,0 +1,10 @@ +value +Formed (normal) +Formed to mounding +Formed with mounding/liquid components +Mounding (soft) +Mounding with liquid components +Liquid +Formed with bloody components +Mounding to liquid with bloody components +Primarily bloody \ No newline at end of file diff --git a/nbri_ehr/resources/data/temperament.tsv b/nbri_ehr/resources/data/temperament.tsv new file mode 100644 index 0000000..7acfc66 --- /dev/null +++ b/nbri_ehr/resources/data/temperament.tsv @@ -0,0 +1,5 @@ +Value Title Category Description Sort Order Date Disabled +Personality +Sociality +Study suitability +Breeding suitability \ No newline at end of file diff --git a/nbri_ehr/resources/data/testicular_volume.tsv b/nbri_ehr/resources/data/testicular_volume.tsv new file mode 100644 index 0000000..28aa0c2 --- /dev/null +++ b/nbri_ehr/resources/data/testicular_volume.tsv @@ -0,0 +1,13 @@ +value sort_order +1 mL 1 +2 mL 2 +3 mL 3 +4 mL 4 +5 mL 5 +6 mL 6 +8 mL 7 +10 mL 8 +12 mL 9 +15 mL 10 +20 mL 11 +25 mL 12 diff --git a/nbri_ehr/resources/data/treatment_frequency.tsv b/nbri_ehr/resources/data/treatment_frequency.tsv new file mode 100644 index 0000000..bbf36e0 --- /dev/null +++ b/nbri_ehr/resources/data/treatment_frequency.tsv @@ -0,0 +1,12 @@ +Meaning Sort Order Week of Month Day of Month Day of Week Interval in Days Short Name Active? Week Days +Monthly 30 true +Weekly 7 true +Alternating Days 2 true +SID 1 true +QID 1 true +TID 1 true +q7 days 7 true +q14 days 14 true +BID 1 true +Every 3 months 90 true +M-F (SID) 1 true 2,3,4,5,6 \ No newline at end of file diff --git a/nbri_ehr/resources/data/treatment_frequency_times.tsv b/nbri_ehr/resources/data/treatment_frequency_times.tsv new file mode 100644 index 0000000..61fd3d6 --- /dev/null +++ b/nbri_ehr/resources/data/treatment_frequency_times.tsv @@ -0,0 +1,18 @@ +Frequency Hour of Day Time Description +SID 800 AM +Monthly 800 AM +Weekly 800 AM +Alternating Days 800 AM +TID 800 AM +TID 1200 PM +TID 1600 PM +QID 800 AM +QID 1100 AM +QID 1400 PM +QID 1700 PM +BID 800 AM +BID 1600 PM +q7 days 800 AM +q14 days 800 AM +Every 3 months 800 AM +M-F (SID) 800 AM \ No newline at end of file diff --git a/nbri_ehr/resources/data/vaginal_uterine_prolapse.tsv b/nbri_ehr/resources/data/vaginal_uterine_prolapse.tsv new file mode 100644 index 0000000..98f995c --- /dev/null +++ b/nbri_ehr/resources/data/vaginal_uterine_prolapse.tsv @@ -0,0 +1,3 @@ +value sort_order +Present 1 +Not present 2 \ No newline at end of file diff --git a/nbri_ehr/resources/data/vendor_approval_code.tsv b/nbri_ehr/resources/data/vendor_approval_code.tsv new file mode 100644 index 0000000..863eb1a --- /dev/null +++ b/nbri_ehr/resources/data/vendor_approval_code.tsv @@ -0,0 +1,4 @@ +value title +1 Approved +2 Not Approved +3 Conditionally Approved \ No newline at end of file diff --git a/nbri_ehr/resources/data/vendor_production_location.tsv b/nbri_ehr/resources/data/vendor_production_location.tsv new file mode 100644 index 0000000..59a4ac9 --- /dev/null +++ b/nbri_ehr/resources/data/vendor_production_location.tsv @@ -0,0 +1,47 @@ +value title description +1 Andover MA 4 +2 Pearl River NY 4 +3 Alice TX 4 +4 West Point PA 4 +5 Bethesda MD 4 +6 Bastrop TX 4 +7 San Antonio TX 4 +8 Homestead FL 4 +9 Atlanta GA 4 +10 Emeryville CA 4 +11 Waltham MA 4 +12 Columbus OH 4 +13 Italy 2 +14 Dickerson MD 4 +15 Bethesda MD 4 +16 Basseterre 1 +17 Yemassee SC 4 +18 Bethesda MD 4 +19 Makati City 5 +20 UL Lafayette - NBRI 4 +21 NBRI +22 Columbus 4 +23 New York 4 +24 Yemassee 4 +25 Three Springs Scientific 4 +26 Sierra Biomedical 4 +27 NIH 4 +28 Lovelace Biomedical 4 +29 University of Washington NPRC 4 +30 "China/Guangxi Grand Forest Sci Primate " 4 +31 Charles River Laboratory 4 +33 Alamogordo Primate Facility 4 +34 Yale Univ Sch Medicine 4 +36 Cornell University Medical College 4 +37 Tulane NPC (Covington) 4 +38 CDC 4 +39 Covance, China 4 +42 St. Helena, SC 4 +44 MD Anderson Cancer Center 4 +45 University of Kentucky 4 +46 Wake Forest School of Medicine 4 +47 Hainan 7 +48 Cynologics Ltd 8 +49 Guangdong 7 +51 Mattawan, MI 4 +52 Phnom Penh 6 diff --git a/nbri_ehr/resources/data/volume_units.tsv b/nbri_ehr/resources/data/volume_units.tsv new file mode 100644 index 0000000..6f20a8c --- /dev/null +++ b/nbri_ehr/resources/data/volume_units.tsv @@ -0,0 +1,16 @@ +Unit +capsule +capsule(s) +cup +drop(s) +gummy +implant +mg +mL +no units +ounce(s) +piece(s) +scoop +tablet +tablet(s) +tsp diff --git a/nbri_ehr/resources/data/weight_ranges.tsv b/nbri_ehr/resources/data/weight_ranges.tsv new file mode 100644 index 0000000..bb2c94f --- /dev/null +++ b/nbri_ehr/resources/data/weight_ranges.tsv @@ -0,0 +1,3 @@ +Species Min Weight Max Weight +Cynomolgus 0.0 20.0 +Rhesus 0.0 35.0 \ No newline at end of file diff --git a/nbri_ehr/resources/data/wound_severity.tsv b/nbri_ehr/resources/data/wound_severity.tsv new file mode 100644 index 0000000..480eaab --- /dev/null +++ b/nbri_ehr/resources/data/wound_severity.tsv @@ -0,0 +1,6 @@ +value sort_order +N/A (0) 1 +Superficial (1) 2 +Partial Thickness (2) 3 +Full Thickness (3) 4 +Muscle Damage (4) 5 \ No newline at end of file diff --git a/nbri_ehr/resources/data/wound_status_behavior.tsv b/nbri_ehr/resources/data/wound_status_behavior.tsv new file mode 100644 index 0000000..c3dbc44 --- /dev/null +++ b/nbri_ehr/resources/data/wound_status_behavior.tsv @@ -0,0 +1,5 @@ +value sort_order +Completely healed 1 +Mostly healed 2 +Partially healed 3 +Not healed 4 \ No newline at end of file diff --git a/nbri_ehr/resources/data/wound_status_clinical.tsv b/nbri_ehr/resources/data/wound_status_clinical.tsv new file mode 100644 index 0000000..a2e6ce0 --- /dev/null +++ b/nbri_ehr/resources/data/wound_status_clinical.tsv @@ -0,0 +1,11 @@ +value sort_order +Healing well 1 +Mostly healed 2 +Completely healed 3 +Cannot visualize 4 +Dehiscence (wound opened) 5 +Necrotic tissue present 6 +Bone exposure on digit(s) 7 +Abscess 8 +Purulent exudate present 9 +Other 10 \ No newline at end of file diff --git a/nbri_ehr/resources/data/yes_no_only.tsv b/nbri_ehr/resources/data/yes_no_only.tsv new file mode 100644 index 0000000..9776fec --- /dev/null +++ b/nbri_ehr/resources/data/yes_no_only.tsv @@ -0,0 +1,3 @@ +value sort_order +Yes 1 +No 2 \ No newline at end of file diff --git a/nbri_ehr/resources/data/yes_no_order.tsv b/nbri_ehr/resources/data/yes_no_order.tsv new file mode 100644 index 0000000..90cd652 --- /dev/null +++ b/nbri_ehr/resources/data/yes_no_order.tsv @@ -0,0 +1,4 @@ +value sort_order +Yes 1 +No 2 +N/A 3 \ No newline at end of file diff --git a/nbri_ehr/resources/domain-templates/ehr.template.xml b/nbri_ehr/resources/domain-templates/ehr.template.xml new file mode 100644 index 0000000..281f4bd --- /dev/null +++ b/nbri_ehr/resources/domain-templates/ehr.template.xml @@ -0,0 +1,125 @@ + + + + + + + + diff --git a/nbri_ehr/resources/domain-templates/ehr_lookups.template.xml b/nbri_ehr/resources/domain-templates/ehr_lookups.template.xml new file mode 100644 index 0000000..36eb0f9 --- /dev/null +++ b/nbri_ehr/resources/domain-templates/ehr_lookups.template.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/folderTypes/NBRI_EHR.folderType.xml b/nbri_ehr/resources/folderTypes/NBRI_EHR.folderType.xml new file mode 100644 index 0000000..2dfc4a4 --- /dev/null +++ b/nbri_ehr/resources/folderTypes/NBRI_EHR.folderType.xml @@ -0,0 +1,70 @@ + + NBRI EHR + Folder type used for the National Biomedical Research Institute's EHR + + + + + + + Electronic Health Record + menu + + + Quick Search + menu + + + + + + overview + Overview + + + EHR Front Page + body + + + + + animalHistory + Animal History + + + animalHistory + + + + + NBRI Animal History + body + + + + + animalSearch + Animal Search + + + animalSearch + + + + + Animal Search + body + + + + + + Core + Study + DataIntegration + EHR + NBRI_EHR + + Core + false + diff --git a/nbri_ehr/resources/module.xml b/nbri_ehr/resources/module.xml new file mode 100644 index 0000000..03d5fae --- /dev/null +++ b/nbri_ehr/resources/module.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/nbri_ehr/resources/queries/ehr/activeProtocols.sql b/nbri_ehr/resources/queries/ehr/activeProtocols.sql new file mode 100644 index 0000000..a33358e --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/activeProtocols.sql @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT protocol, title FROM ehr.protocol pr +WHERE pr.inactiveDate IS NULL OR pr.inactiveDate > now() \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/my_tasks.query.xml b/nbri_ehr/resources/queries/ehr/my_tasks.query.xml new file mode 100644 index 0000000..2a6ca88 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/my_tasks.query.xml @@ -0,0 +1,65 @@ + + + + + My Tasks + + + + RowId + + + Task Id + true + true + + + Task Type + + + Assigned To + true + + core + PrincipalsWithoutAdmin + userid + + + + Due Date + true + DateTime + + + Created By + + + Created + + + Modified By + + + Modified + + + + ehr.context + /ehr/studyButtons.js + + Grid Views + + + Charts + + + Export + + + Print + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/ehr/my_tasks.sql b/nbri_ehr/resources/queries/ehr/my_tasks.sql new file mode 100644 index 0000000..dae6220 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/my_tasks.sql @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + +taskid, +rowid, +updateTitle, +category, +title, +formtype, +qcstate, +assignedto, +duedate, +requestid, +datecompleted, +modifiedby, +modified, +createdby, +created, +description + + +FROM ehr.tasks t + +WHERE ISMEMBEROF(t.assignedto) \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/my_tasks/.qview.xml b/nbri_ehr/resources/queries/ehr/my_tasks/.qview.xml new file mode 100644 index 0000000..8388595 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/my_tasks/.qview.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/my_tasks/Active Tasks.qview.xml b/nbri_ehr/resources/queries/ehr/my_tasks/Active Tasks.qview.xml new file mode 100644 index 0000000..069ab01 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/my_tasks/Active Tasks.qview.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/my_tasks/Review Required.qview.xml b/nbri_ehr/resources/queries/ehr/my_tasks/Review Required.qview.xml new file mode 100644 index 0000000..d02c415 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/my_tasks/Review Required.qview.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/observation_types.query.xml b/nbri_ehr/resources/queries/ehr/observation_types.query.xml new file mode 100644 index 0000000..16fbabe --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/observation_types.query.xml @@ -0,0 +1,17 @@ + + + + + Observation Types + + + false + + + true + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/project.js b/nbri_ehr/resources/queries/ehr/project.js new file mode 100644 index 0000000..bb57d44 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/project.js @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +require("ehr/triggers").initScript(this); +var nextProjectNum = -1; + +function onInit(event, helper){ + + //ETL'd data has integer values in the 'project' column that is meaningless to the client, + //but since 'project' is a required field, find the highest num in the existing data and add 1 for inserting new Projects. + LABKEY.Query.executeSql({ + schemaName: 'ehr', + sql: 'SELECT MAX(project) AS latestProjectNum FROM ehr.project', + containerFilter: LABKEY.Query.containerFilter.allFolders, + success: function(data) { + nextProjectNum = data.rows[0].latestProjectNum + 1; + }, + failure: function (error) { + console.log("Error getting the latest 'Project Id' in project trigger onInit()\n" + error); + } + }); +} +function onUpsert(helper, scriptErrors, row, oldRow) { + if (!helper.isETL()) { + if (!row.project) { + row.project = nextProjectNum; + } + } +} \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/project.query.xml b/nbri_ehr/resources/queries/ehr/project.query.xml new file mode 100644 index 0000000..d2db2ca --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/project.query.xml @@ -0,0 +1,75 @@ + + + + + + /EHR/projectDetails.view?project=${project} + + + + + + + Project + false + NBRI Project + + + Project Id + true + + + true + + + true + + + true + + + IACUC Protocol + true + + ehr + protocol + protocol + + + + true + + + true + + + true + + + true + + + true + + + true + + + Investigator + true + + + Requestor Name + true + + + true + + + true + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/ehr/project/.qview.xml b/nbri_ehr/resources/queries/ehr/project/.qview.xml new file mode 100644 index 0000000..2022e60 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/project/.qview.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/protocol.js b/nbri_ehr/resources/queries/ehr/protocol.js new file mode 100644 index 0000000..73eb714 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocol.js @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +require("ehr/triggers").initScript(this); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_INSERT, 'ehr', 'protocol', function (helper, scriptErrors, row, oldRow) { + + if (row.description) { + plainTextParts = row.description.split("\\loch\\af0") + let plainText = ""; + for(let i = 1; i < plainTextParts.length; i++) + { + let chunk = LABKEY.Utils.encodeHtml(plainTextParts[i].split("}")[0]); + chunk = chunk.replace("\\hich\\af0 \\'85", "…"); // ellipsis + chunk = chunk.replace("\\hich\\af0 \\'92", "'"); + chunk = chunk.replace("\\hich\\af0 \\'93", "\""); + chunk = chunk.replace("\\hich\\af0 \\'94", "\""); + chunk = chunk.replace("\\hich\\af0 \\'99", "™"); // trademark + chunk = chunk.replace("\\hich\\af0 \\'ae", "®"); // registered trademark + chunk = chunk.replace("\\hich\\af0 \\'b0", "°"); // Degree sign + chunk = chunk.replace("\\hich\\af0 \\'b5", "µ"); // Micro sign (Greek mu) + chunk = chunk.replace("\\hich\\af0 \\'b7", "·"); // Middle dot + chunk = chunk.replace("\\hich\\af0 \\'ef", "ï"); // i-diaeresis + // TODO: As a general catch all, could convert the hex value in the match to the HTML ascii entity + // Currently this covers all the cases though in the source data + + plainText += chunk.trim(); + plainText += " "; + + } + row.description = plainText.trim(); + } + +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/protocol.query.xml b/nbri_ehr/resources/queries/ehr/protocol.query.xml new file mode 100644 index 0000000..82667e7 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocol.query.xml @@ -0,0 +1,91 @@ + + + + + + Protocol + + + PI + false + + core + Users + UserId + DisplayName + + + + true + + + Author + + core + Users + UserId + DisplayName + + + + Owner + + core + Users + UserId + DisplayName + + + + Protocol Type + + ehr_lookups + protocol_type + value + title + + + + Protocol Category + + ehr_lookups + protocol_category + value + title + + + + Current State + + ehr_lookups + protocol_state + value + title + + + + Parent Protocol + + ehr + protocol + protocol + displayName + + + + Questionnaire + + ehr_lookups + questionnaire + value + title + + + + Approval Date + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/protocol/.qview.xml b/nbri_ehr/resources/queries/ehr/protocol/.qview.xml new file mode 100644 index 0000000..e2e125f --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocol/.qview.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/protocolActiveAnimals.query.xml b/nbri_ehr/resources/queries/ehr/protocolActiveAnimals.query.xml new file mode 100644 index 0000000..623b9ea --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocolActiveAnimals.query.xml @@ -0,0 +1,29 @@ + + + + + Animals Actively Assigned to Each Protocol + + + true + + ehr + protocol + protocol + + + + /query/executeQuery.view?schemaName=study& + query.queryName=protocolAssignment& + query.viewName=Active Assignments& + query.protocol~eq=${protocol}& + + + + + + TotalActiveAnimals +
+
+
+
diff --git a/nbri_ehr/resources/queries/ehr/protocolActiveAnimals.sql b/nbri_ehr/resources/queries/ehr/protocolActiveAnimals.sql new file mode 100644 index 0000000..eaae125 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocolActiveAnimals.sql @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + p.protocol, + p.title, + count(distinct a.Id) AS TotalActiveAnimals, + group_concat(distinct a.Id) AS ActiveAnimals + +FROM ehr.protocol p + +--we find total distinct animals ever assigned to this protocol +LEFT JOIN + (SELECT a.protocol, a.id, count(*) AS TotalAssignments, max(a.date) as LatestStart, + max(a.enddateCoalesced) as latestEnd + FROM study.protocolAssignment a + GROUP BY a.protocol, a.id) a ON (p.protocol = a.protocol.protocol) + +group by p.protocol, p.title \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/protocolAnimals.query.xml b/nbri_ehr/resources/queries/ehr/protocolAnimals.query.xml new file mode 100644 index 0000000..f9500ac --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocolAnimals.query.xml @@ -0,0 +1,43 @@ + + + + + Distinct animals ever assigned to this protocol, over the full history + + + true + + ehr + protocol + protocol + + + + + study + animal + id + + + + + ehr_lookups + species + common + + + + + + /query/executeQuery.view?schemaName=study& + query.queryName=protocolAssignment& + query.protocol~eq=${protocol}& + query.id~eq=${id}& + query.sort=-Date& + + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/ehr/protocolAnimals.sql b/nbri_ehr/resources/queries/ehr/protocolAnimals.sql new file mode 100644 index 0000000..07ecee9 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocolAnimals.sql @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + p.protocol, + p.approve, + a.id, + a.species, + + COALESCE(a.Total, 0) AS TotalAssignments + +FROM ehr.protocol p + +--we find total distinct animals ever assigned to this protocol, since the last approval date +LEFT JOIN + (SELECT a.protocol.displayName as protocol, a.id, a.id.dataset.demographics.Species AS Species, count(*) AS Total, max(a.date) as LatestStart, + max(a.enddateCoalesced) as latestEnd + FROM study.protocolAssignment a + GROUP BY a.protocol.displayName, a.id, a.id.dataset.demographics.species) a ON (p.displayName = a.protocol) + diff --git a/nbri_ehr/resources/queries/ehr/protocolHistoricAnimals.sql b/nbri_ehr/resources/queries/ehr/protocolHistoricAnimals.sql new file mode 100644 index 0000000..3992249 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocolHistoricAnimals.sql @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + p.protocol, + p.approve, + a.id, + a.species, + a.LatestStart, + a.LatestEnd, + + COALESCE(a.Total, 0) AS TotalAssignments + +FROM ehr.protocol p + +--we find total distinct animals ever assigned to this protocol +LEFT JOIN + (SELECT a.Project.protocol as protocol, a.id, a.id.dataset.demographics.Species AS Species, count(*) AS Total, max(a.date) as LatestStart, + max(a.enddateCoalesced) as latestEnd + FROM study.assignment a + GROUP BY a.project.protocol, a.id, a.id.dataset.demographics.species) a + ON (p.protocol = a.protocol) + +WHERE a.Total > 0 diff --git a/nbri_ehr/resources/queries/ehr/protocolTotalAnimalsBySpecies.query.xml b/nbri_ehr/resources/queries/ehr/protocolTotalAnimalsBySpecies.query.xml new file mode 100644 index 0000000..302482d --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocolTotalAnimalsBySpecies.query.xml @@ -0,0 +1,36 @@ + + + + + Total Animals Assigned To Each Protocol, By Species + + + true + + ehr + protocol + protocol + + + + Species + + ehr_lookups + species + common + + + + + /query/executeQuery.view?schemaName=ehr& + query.queryName=protocolAnimals& + query.protocol~eq=${protocol}& + query.species~eq=${species}& + + + + TotalAnimals +
+
+
+
diff --git a/nbri_ehr/resources/queries/ehr/protocolTotalAnimalsBySpecies.sql b/nbri_ehr/resources/queries/ehr/protocolTotalAnimalsBySpecies.sql new file mode 100644 index 0000000..a4aa9b9 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocolTotalAnimalsBySpecies.sql @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT i.* FROM ( + SELECT + p.protocol as protocol, + pa.species, + group_concat(DISTINCT pa.id) as Animals, + CONVERT(Count(pa.id), INTEGER) AS TotalAnimals + FROM ehr.protocol p + LEFT JOIN ehr.protocolAnimals pa ON (p.protocol = pa.protocol) + GROUP BY p.protocol, pa.species +) i +WHERE i.species IS NOT NULL + + diff --git a/nbri_ehr/resources/queries/ehr/protocol_counts.query.xml b/nbri_ehr/resources/queries/ehr/protocol_counts.query.xml new file mode 100644 index 0000000..6586f91 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocol_counts.query.xml @@ -0,0 +1,30 @@ + + + + + NHPs Allowed Per Protocol + + + + Species + + ehr_lookups + species_codes + code + scientific_name + + + + Euthanasia + + ehr_lookups + euthanasia_type + value + title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/protocol_counts/.qview.xml b/nbri_ehr/resources/queries/ehr/protocol_counts/.qview.xml new file mode 100644 index 0000000..c932369 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/protocol_counts/.qview.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/tasks/.qview.xml b/nbri_ehr/resources/queries/ehr/tasks/.qview.xml new file mode 100644 index 0000000..b60dc1d --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/tasks/.qview.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/tasks/Active Tasks.qview.xml b/nbri_ehr/resources/queries/ehr/tasks/Active Tasks.qview.xml new file mode 100644 index 0000000..33364dc --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/tasks/Active Tasks.qview.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr/tasks/Review Required.qview.xml b/nbri_ehr/resources/queries/ehr/tasks/Review Required.qview.xml new file mode 100644 index 0000000..ac3cbd6 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/tasks/Review Required.qview.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/ageclass.query.xml b/nbri_ehr/resources/queries/ehr_lookups/ageclass.query.xml new file mode 100644 index 0000000..7aa4864 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/ageclass.query.xml @@ -0,0 +1,45 @@ + + + + + Age Class + + + Key + false + true + true + + + Species + + ehr_lookups + species_codes + code + common_name + + + + Gender + + ehr_lookups + gender_codes + code + meaning + + + + Age Class + + + Min + + + Max + + + key +
+
+
+
diff --git a/nbri_ehr/resources/queries/ehr_lookups/areas/.qview.xml b/nbri_ehr/resources/queries/ehr_lookups/areas/.qview.xml new file mode 100644 index 0000000..bac04f3 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/areas/.qview.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/buildings.js b/nbri_ehr/resources/queries/ehr_lookups/buildings.js new file mode 100644 index 0000000..3fca085 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/buildings.js @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +var LABKEY = require("labkey"); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +function onUpsert(row, oldRow, errors){ + if (extraContext.dataSource != "etl") { + if (!row.description) { + errors['description'] = 'Building description is required.'; + return; + } + + if (!row.area) { + errors['area'] = 'Area is required.'; + return; + } + + if (!row.name) { + if (oldRow && oldRow.name && oldRow.name[0]) { + row.name = oldRow.name[0]; + return; + } + + row.name = row.description + '-' + row.area; + } + } +} + +function beforeInsert(row, errors){ + onUpsert(row, undefined, errors); +} + +function beforeUpdate(row, oldRow, errors){ + onUpsert(row, oldRow, errors); +} + +function beforeDelete(row, errors) { + if (extraContext.dataSource != "etl") { + if (!row.name) { + errors[null] = 'Building name is required.'; + } + else { + let totalRecords = triggerHelper.totalRecords("ehr_lookups", "floors", "building", row.name); + if (totalRecords > 0) { + errors[null] = 'Cannot delete. There are ' + totalRecords + ' floors currently registered in this building. Delete floors before deleting this building.'; + } + } + } +} \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/buildings.query.xml b/nbri_ehr/resources/queries/ehr_lookups/buildings.query.xml new file mode 100644 index 0000000..90dd3ea --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/buildings.query.xml @@ -0,0 +1,31 @@ + + + + + Buildings + + + + + Area + + ehr_lookups + areas + area + description + + + + true + false + false + false + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/buildings/.qview.xml b/nbri_ehr/resources/queries/ehr_lookups/buildings/.qview.xml new file mode 100644 index 0000000..6dab0af --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/buildings/.qview.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/cage.js b/nbri_ehr/resources/queries/ehr_lookups/cage.js new file mode 100644 index 0000000..e19a2b7 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/cage.js @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +var LABKEY = require("labkey"); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +function onUpsert(row, oldRow, errors){ + if (extraContext.dataSource != "etl") { + if (!row.location) { + if (oldRow && oldRow.location && oldRow.location[0]) { + row.location = oldRow.location[0]; + return; + } + + if (!row.room) { + errors['room'] = 'Room is required.'; + return; + } + + row.location = row.room; + if (row.cage) + row.location += '-' + row.cage; + } + } +} + +function beforeInsert(row, errors){ + onUpsert(row, undefined, errors); +} + +function beforeUpdate(row, oldRow, errors){ + onUpsert(row, oldRow, errors); +} + +function beforeDelete(row, errors) { + if (extraContext.dataSource != "etl") { + if (!row.location) { + errors[null] = 'Location is required.'; + } + else { + let currentlyHoused = triggerHelper.totalHousingRecords(row.location); + if (currentlyHoused > 0) { + errors[null] = 'Cannot delete. There are ' + currentlyHoused + ' animals currently housed in this cage.'; + } + } + } +} \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/cage.query.xml b/nbri_ehr/resources/queries/ehr_lookups/cage.query.xml new file mode 100644 index 0000000..97b1549 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/cage.query.xml @@ -0,0 +1,29 @@ + + + + + Cages + + + /nbri_ehr/cageDetails.view?room=${room}&cage=${location}& + + + Room + + + true + false + + + Indoor/Outdoor + + ehr_lookups + indoor_outdoor + value + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/cage/.qview.xml b/nbri_ehr/resources/queries/ehr_lookups/cage/.qview.xml new file mode 100644 index 0000000..5f0ff5c --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/cage/.qview.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/country.query.xml b/nbri_ehr/resources/queries/ehr_lookups/country.query.xml new file mode 100644 index 0000000..0cfb2c9 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/country.query.xml @@ -0,0 +1,20 @@ + + + + + Country + + + Category + + ehr_lookups + country_category + value + title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/floors.js b/nbri_ehr/resources/queries/ehr_lookups/floors.js new file mode 100644 index 0000000..f2327a4 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/floors.js @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +var LABKEY = require("labkey"); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +function onUpsert(row, oldRow, errors){ + if (extraContext.dataSource != "etl") { + if (!row.name) { + errors['name'] = 'Floor name is required.'; + return; + } + + if (!row.building) { + errors['building'] = 'Building is required.'; + return; + } + + if (!row.floor) { + if (oldRow && oldRow.floor && oldRow.floor[0]) { + row.floor = oldRow.floor[0]; + return; + } + + row.floor = row.name + '-' + row.building; + } + } +} + +function beforeInsert(row, errors){ + onUpsert(row, undefined, errors); +} + +function beforeUpdate(row, oldRow, errors){ + onUpsert(row, oldRow, errors); +} + +function beforeDelete(row, errors) { + if (extraContext.dataSource != "etl") { + if (!row.floor) { + errors[null] = 'Floor is required.'; + } + else { + let totalRecords = triggerHelper.totalRecords("ehr_lookups", "rooms", "floor", row.floor); + if (totalRecords > 0) { + errors[null] = 'Cannot delete. There are ' + totalRecords + ' rooms currently registered on this floor. Delete rooms before deleting this floor.'; + } + } + } +} \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/floors.query.xml b/nbri_ehr/resources/queries/ehr_lookups/floors.query.xml new file mode 100644 index 0000000..ba3ff03 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/floors.query.xml @@ -0,0 +1,28 @@ + + + + + Floors + + + + + Building + + ehr_lookups + buildings + name + description + + + + true + false + false + false + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/floors/.qview.xml b/nbri_ehr/resources/queries/ehr_lookups/floors/.qview.xml new file mode 100644 index 0000000..f8c6e5e --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/floors/.qview.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/procedures/.qview.xml b/nbri_ehr/resources/queries/ehr_lookups/procedures/.qview.xml new file mode 100644 index 0000000..a2af545 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/procedures/.qview.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/roomUtilization.query.xml b/nbri_ehr/resources/queries/ehr_lookups/roomUtilization.query.xml new file mode 100644 index 0000000..dacb1a3 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/roomUtilization.query.xml @@ -0,0 +1,22 @@ + + + + + Room Utilization + + + + Total Animals + /query/executeQuery.view? + schemaName=study& + query.queryName=Housing& + query.room~eq=${room}& + query.sort=Id& + query.enddate~isblank + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/roomUtilization.sql b/nbri_ehr/resources/queries/ehr_lookups/roomUtilization.sql new file mode 100644 index 0000000..de3fa9e --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/roomUtilization.sql @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +SELECT + r.room, + count(DISTINCT h.id) as TotalAnimals, + r.building, + r.area, +FROM ehr_lookups.rooms r +LEFT JOIN study.housing h +ON r.room = h.room + +GROUP BY r.room, r.building, r.area \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/roomUtilizationByBuilding.query.xml b/nbri_ehr/resources/queries/ehr_lookups/roomUtilizationByBuilding.query.xml new file mode 100644 index 0000000..8177e14 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/roomUtilizationByBuilding.query.xml @@ -0,0 +1,81 @@ + + + + + Room Utilization By Building + + + + true + + + Total Cage Spaces + 40 + /query/executeQuery.view? + schemaName=ehr_lookups& + query.queryName=cage& + query.room/building~eq=${building}& + query.sort=cage& + + + + Total Cages Present + 40 + /query/executeQuery.view? + schemaName=ehr_lookups& + query.queryName=availableCages& + query.room/building~eq=${building}& + query.isAvailable~eq=true& + query.sort=cage& + + + + Cages Used + 40 + /query/executeQuery.view? + schemaName=ehr_lookups& + query.queryName=cage& + query.room/building~eq=${building}& + query.availability/isAvailable~eq=true& + query.totalAnimals/totalAnimals~gt=0& + query.sort=cage& + + + + Cages Empty + 40 + /query/executeQuery.view? + schemaName=ehr_lookups& + query.queryName=cage& + query.room/building~eq=${building}& + query.availability/isAvailable~eq=true& + query.totalAnimals/totalAnimals~isblank& + query.sort=cage& + + + + 40 + % Used + 0.## + + + 40 + % Empty + 0.## + + + Total Animals + 40 + /query/executeQuery.view? + schemaName=study& + query.queryName=Demographics& + query.viewName=By Location& + query.Id/curLocation/room/building~eq=${building}& + query.sort=Id& + + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/ehr_lookups/roomUtilizationByBuilding.sql b/nbri_ehr/resources/queries/ehr_lookups/roomUtilizationByBuilding.sql new file mode 100644 index 0000000..64889e8 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/roomUtilizationByBuilding.sql @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + t1.building, + t1.totalRooms, +-- t1.totalCages, +-- t1.availableCages, +-- t1.cagesUsed, +-- t1.cagesEmpty, +-- cast(((CAST(t1.cagesUsed as double) / t1.availableCages) * 100) as double) as pctUsed, +-- cast((100.0 - ((CAST(t1.cagesUsed as double) / t1.availableCages) * 100)) as double) as pctEmpty, + t1.totalAnimals + +FROM ( +SELECT + r.room.building as building, + count(DISTINCT r.room) as totalRooms, +-- sum(r.totalCages) as totalCages, +-- sum(r.availableCages) as availableCages, +-- sum(r.cagesUsed) as cagesUsed, +-- sum(r.cagesEmpty) as cagesEmpty, + sum(r.totalAnimals) as totalAnimals + +FROM ehr_lookups.roomUtilization r +GROUP BY r.room.building + +) t1 \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/rooms.js b/nbri_ehr/resources/queries/ehr_lookups/rooms.js new file mode 100644 index 0000000..caea28b --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/rooms.js @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +var LABKEY = require("labkey"); +var console = require("console"); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +function onUpsert(row, oldRow, errors){ + if (extraContext.dataSource != "etl") { + if (!row.name) { + errors['name'] = 'Room name is required.'; + return; + } + + if (!row.floor) { + errors['floor'] = 'Floor is required.'; + return; + } + + if (!row.room) { + if (oldRow && oldRow.room && oldRow.room[0]) { + row.room = oldRow.room[0]; + return; + } + + row.room = row.name + '-' + row.floor; + } + } +} + +function beforeInsert(row, errors){ + onUpsert(row, undefined, errors); +} + +function beforeUpdate(row, oldRow, errors){ + onUpsert(row, oldRow, errors); +} + +function beforeDelete(row, errors) { + if (extraContext.dataSource != "etl") { + if (!row.room) { + errors[null] = 'Room is required.'; + } + else { + let totalRecords = triggerHelper.totalRecords("ehr_lookups", "cage", "room", row.room); + if (totalRecords > 0) { + errors[null] = 'Cannot delete. There are ' + totalRecords + ' cages currently registered in this room. Delete cages before deleting this room.'; + } + } + } +} \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/rooms.query.xml b/nbri_ehr/resources/queries/ehr_lookups/rooms.query.xml new file mode 100644 index 0000000..dd7b89f --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/rooms.query.xml @@ -0,0 +1,24 @@ + + + + + + Rooms + + + + + true + false + false + + + true + false + false + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/rooms/.qview.xml b/nbri_ehr/resources/queries/ehr_lookups/rooms/.qview.xml new file mode 100644 index 0000000..0bfbf5b --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/rooms/.qview.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/snomed.query.xml b/nbri_ehr/resources/queries/ehr_lookups/snomed.query.xml new file mode 100644 index 0000000..4613f3e --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/snomed.query.xml @@ -0,0 +1,9 @@ + + + + + Treatments +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/species_codes.query.xml b/nbri_ehr/resources/queries/ehr_lookups/species_codes.query.xml new file mode 100644 index 0000000..fab66c2 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/species_codes.query.xml @@ -0,0 +1,19 @@ + + + + + + + Scientific Name + + ehr_lookups + species + scientific_name + scientific_name + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/ehr_lookups/vendor_production_location.query.xml b/nbri_ehr/resources/queries/ehr_lookups/vendor_production_location.query.xml new file mode 100644 index 0000000..058877b --- /dev/null +++ b/nbri_ehr/resources/queries/ehr_lookups/vendor_production_location.query.xml @@ -0,0 +1,19 @@ + + + + + + + Country + + ehr_lookups + country + value + title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/Account.query.xml b/nbri_ehr/resources/queries/nbri_ehr/Account.query.xml new file mode 100644 index 0000000..7f498db --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/Account.query.xml @@ -0,0 +1,48 @@ + + + + + Account + + + + Department + + nbri_ehr + Department + DepartmentId + Name + + + + Cost Type + + ehr_lookups + cost_type + value + title + + + + Expense Class + + ehr_lookups + expense_class + value + description + + + + Project + + ehr + project + project + displayName + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/AnimalDelivery.query.xml b/nbri_ehr/resources/queries/nbri_ehr/AnimalDelivery.query.xml new file mode 100644 index 0000000..e19c0a8 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/AnimalDelivery.query.xml @@ -0,0 +1,86 @@ + + + + + Animal Delivery + + + + Animal Delivery Id + + + Animal Shipment + + nbri_ehr + AnimalShipment + AnimalShipmentId + AnimalShipmentId + + + + Ship To + + nbri_ehr + ShipTo + ShipToId + Name + + + + Animal Req Order + + nbri_ehr + AnimalReqOrder + AnimalReqOrderId + AnimalReqOrder + + + + Delivery State + + ehr_lookups + delivery_state + value + title + + + + Project + + ehr + project + project + displayName + + + + Bill To Account + + nbri_ehr + Account + AccountId + AccountNumber + + + + Bill To Staff + http://www.labkey.org/types#userId + + + Per Diem Account + + nbri_ehr + Account + AccountId + AccountNumber + + + + Per Diem Staff + http://www.labkey.org/types#userId + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/AnimalDeliveryEsig.query.xml b/nbri_ehr/resources/queries/nbri_ehr/AnimalDeliveryEsig.query.xml new file mode 100644 index 0000000..0c74ac4 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/AnimalDeliveryEsig.query.xml @@ -0,0 +1,36 @@ + + + + + Animal Delivery ESignature + + + Animal Delivery + + nbri_ehr + AnimalDelivery + AnimalDeliveryId + AnimalDeliveryId + + + + Esig Event + + ehr_lookups + esig_events + value + title + + + + User Profile + http://www.labkey.org/types#userId + + + Esig Date + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/AnimalReqOrder.query.xml b/nbri_ehr/resources/queries/nbri_ehr/AnimalReqOrder.query.xml new file mode 100644 index 0000000..5c829e1 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/AnimalReqOrder.query.xml @@ -0,0 +1,135 @@ + + + + + Animal Req Order + + + + Animal Vendor + + nbri_ehr + AnimalVendor + AnimalVendorId + VendorName + + + + Requisitioner Staff + http://www.labkey.org/types#userId + + + Req Order Type + + ehr_lookups + req_order_type + value + title + + + + Req Order State + + ehr_lookups + req_order_state + value + title + + + + Bill To Account + + nbri_ehr + Account + AccountId + AccountNumber + + + + Bill To Staff + http://www.labkey.org/types#userId + + + Per Diem Account + + nbri_ehr + Account + AccountId + AccountNumber + + + + Per Diem Staff + http://www.labkey.org/types#userId + + + Submitted By Staff + http://www.labkey.org/types#userId + + + Approved By Staff + http://www.labkey.org/types#userId + + + Project + + ehr + project + project + displayName + + + + Site Cage + /nbri_ehr/cageDetails.view?room=${SiteCage/room}&cage=${SiteCage}& + + ehr_lookups + cage + location + cage + + + + Site Room + /nbri_ehr/cageDetails.view?room=${SiteRoom}& + + ehr_lookups + rooms + room + name + + + + Site Floor + + ehr_lookups + floors + floor + name + + + + Site Building + + ehr_lookups + buildings + name + + + + Site Area + + ehr_lookups + areas + area + + + + Created By Staff + http://www.labkey.org/types#userId + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/AnimalReqOrderEsig.query.xml b/nbri_ehr/resources/queries/nbri_ehr/AnimalReqOrderEsig.query.xml new file mode 100644 index 0000000..2d8bfb2 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/AnimalReqOrderEsig.query.xml @@ -0,0 +1,36 @@ + + + + + Animal Req Order ESignature + + + Animal Req Order + + nbri_ehr + AnimalReqOrder + AnimalReqOrderId + AnimalReqOrderId + + + + Esig Event + + ehr_lookups + esig_events + value + title + + + + User Profile + http://www.labkey.org/types#userId + + + Esig Date + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/AnimalShipment.query.xml b/nbri_ehr/resources/queries/nbri_ehr/AnimalShipment.query.xml new file mode 100644 index 0000000..60aa8de --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/AnimalShipment.query.xml @@ -0,0 +1,42 @@ + + + + + Animal Shipment + + + + Received By Staff + http://www.labkey.org/types#userId + + + Animal Delivery + + nbri_ehr + AnimalDelivery + AnimalDeliveryId + AnimalDeliveryId + + + + Lot Id + + nbri_ehr + lot + lotId + + + + Cost Center + + ehr_lookups + cost_center + value + title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/AnimalVendor.query.xml b/nbri_ehr/resources/queries/nbri_ehr/AnimalVendor.query.xml new file mode 100644 index 0000000..426952f --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/AnimalVendor.query.xml @@ -0,0 +1,29 @@ + + + + + Animal Vendor + + + Vendor Approval Code + + ehr_lookups + vendor_approval_code + value + title + + + + Vendor Production Location + + ehr_lookups + vendor_production_location + value + title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/AnimalVendor/.qview.xml b/nbri_ehr/resources/queries/nbri_ehr/AnimalVendor/.qview.xml new file mode 100644 index 0000000..9691552 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/AnimalVendor/.qview.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/CageCard.query.xml b/nbri_ehr/resources/queries/nbri_ehr/CageCard.query.xml new file mode 100644 index 0000000..e70dfc5 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/CageCard.query.xml @@ -0,0 +1,56 @@ + + + + + Cage Card + + + + Account Staff + http://www.labkey.org/types#userId + + + Account Staff + http://www.labkey.org/types#userId + + + Animal Delivery + + nbri_ehr + AnimalDelivery + AnimalDeliveryId + AnimalDeliveryId + + + + Cost Center + + ehr_lookups + cost_center + value + title + + + + Card Format + + ehr_lookups + card_format + value + title + + + + Census Activity Status + + ehr_lookups + census_activity_status + value + title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/CageCardHistory.query.xml b/nbri_ehr/resources/queries/nbri_ehr/CageCardHistory.query.xml new file mode 100644 index 0000000..088f8b4 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/CageCardHistory.query.xml @@ -0,0 +1,65 @@ + + + + + Cage Card History + + + + Account Staff + http://www.labkey.org/types#userId + + + Account Staff + http://www.labkey.org/types#userId + + + Animal Delivery + + nbri_ehr + AnimalDelivery + AnimalDeliveryId + AnimalDeliveryId + + + + Cost Center + + ehr_lookups + cost_center + value + title + + + + Card Format + + ehr_lookups + card_format + value + title + + + + Census Activity Status + + ehr_lookups + census_activity_status + value + title + + + + Account + + nbri_ehr + Account + AccountId + AccountNumber + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/DeletedRecord.query.xml b/nbri_ehr/resources/queries/nbri_ehr/DeletedRecord.query.xml new file mode 100644 index 0000000..6b894a7 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/DeletedRecord.query.xml @@ -0,0 +1,24 @@ + + + + + Deleted Record + + + Esig Event + + ehr_lookups + esig_events + value + title + + + + ESignature User + http://www.labkey.org/types#userId + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/Department.query.xml b/nbri_ehr/resources/queries/nbri_ehr/Department.query.xml new file mode 100644 index 0000000..91062cf --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/Department.query.xml @@ -0,0 +1,25 @@ + + + + + Department + + + + Parent Department + + nbri_ehr + Department + DepartmentId + Name + + + + Staff + http://www.labkey.org/types#userId + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/IdHistory.query.xml b/nbri_ehr/resources/queries/nbri_ehr/IdHistory.query.xml new file mode 100644 index 0000000..686bf4c --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/IdHistory.query.xml @@ -0,0 +1,29 @@ + + + + + Id History + + + Id + + study + Animal + Id + Id + + + + Type + + ehr_lookups + id_history_type + Value + Title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/Lot.query.xml b/nbri_ehr/resources/queries/nbri_ehr/Lot.query.xml new file mode 100644 index 0000000..a5de660 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/Lot.query.xml @@ -0,0 +1,20 @@ + + + + + Animal Lot + + + Animal Shipment + + nbri_ehr + AnimalShipment + AnimalShipmentId + AnimalShipmentId + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/ProtocolEsig.query.xml b/nbri_ehr/resources/queries/nbri_ehr/ProtocolEsig.query.xml new file mode 100644 index 0000000..366d740 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/ProtocolEsig.query.xml @@ -0,0 +1,31 @@ + + + + + Protocol ESignature + + + + Esig Id + + + Esig Event + + ehr_lookups + esig_events + value + title + + + + User Profile + http://www.labkey.org/types#userId + + + Esig Date + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/ProtocolProcedures.query.xml b/nbri_ehr/resources/queries/nbri_ehr/ProtocolProcedures.query.xml new file mode 100644 index 0000000..27ee2e0 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/ProtocolProcedures.query.xml @@ -0,0 +1,21 @@ + + + + + Protocol Procedures + + + + Procedures + + ehr_lookups + procedures + name + name + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/ProtocolStress.query.xml b/nbri_ehr/resources/queries/nbri_ehr/ProtocolStress.query.xml new file mode 100644 index 0000000..2b1ca94 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/ProtocolStress.query.xml @@ -0,0 +1,21 @@ + + + + + Protocol Stress + + + + Stress + + nbri_ehr + Stress + StressId + Name + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/QuestionResponse.js b/nbri_ehr/resources/queries/nbri_ehr/QuestionResponse.js new file mode 100644 index 0000000..537630a --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/QuestionResponse.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_INSERT, 'nbri_ehr', 'QuestionResponse', function (helper, scriptErrors, row, oldRow) { + + if (row.Response) { + plainTextParts = row.Response.split("\\loch\\af0") + let plainText = ""; + for(let i = 1; i < plainTextParts.length; i++) + { + let chunk = LABKEY.Utils.encodeHtml(plainTextParts[i].split("}")[0]); + chunk = chunk.replace("\\hich\\af0 \\'85", "…"); // ellipsis + chunk = chunk.replace("\\hich\\af0 \\'92", "'"); + chunk = chunk.replace("\\hich\\af0 \\'93", "\""); + chunk = chunk.replace("\\hich\\af0 \\'94", "\""); + chunk = chunk.replace("\\hich\\af0 \\'99", "™"); // trademark + chunk = chunk.replace("\\hich\\af0 \\'ae", "®"); // registered trademark + chunk = chunk.replace("\\hich\\af0 \\'b0", "°"); // Degree sign + chunk = chunk.replace("\\hich\\af0 \\'b5", "µ"); // Micro sign (Greek mu) + chunk = chunk.replace("\\hich\\af0 \\'b7", "·"); // Middle dot + chunk = chunk.replace("\\hich\\af0 \\'ef", "ï"); // i-diaeresis + // TODO: As a general catch all, could convert the hex value in the match to the HTML ascii entity + // Currently this covers all the cases though in the source data + + plainText += chunk.trim(); + plainText += " "; + } + row.Response = plainText.trim(); + } + +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/QuestionResponse.query.xml b/nbri_ehr/resources/queries/nbri_ehr/QuestionResponse.query.xml new file mode 100644 index 0000000..218470d --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/QuestionResponse.query.xml @@ -0,0 +1,38 @@ + + + + + Question Response + + + Protocol + + ehr + protocol + objectid + protocol + + + + Question + + nbri_ehr + Question + QuestionId + Text + + + + Questionnaire + + ehr_lookups + questionnaire + value + title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/dateRange.sql b/nbri_ehr/resources/queries/nbri_ehr/dateRange.sql new file mode 100644 index 0000000..aadf062 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/dateRange.sql @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +PARAMETERS(StartDate TIMESTAMP, NumDays INTEGER DEFAULT 1) + +SELECT +i.date, +CAST(i.date as date) as dateOnly, +cast(dayofyear(i.date) as integer) as DayOfYear, +cast(dayofmonth(i.date) as integer) as DayOfMonth, +cast(dayofweek(i.date) as integer) as DayOfWeek, +ceiling(cast(dayofmonth(i.date) as float) / 7.0) as WeekOfMonth, +cast(week(i.date) as integer) as WeekOfYear, +CAST(StartDate AS TIMESTAMP) as startDate @hidden, +cast(NumDays as integer) as numDays @hidden + +FROM (SELECT + +timestampadd('SQL_TSI_DAY', i.value, CAST(COALESCE(CAST(StartDate as date), curdate()) AS TIMESTAMP)) as date + +FROM ldk.integers i + +WHERE i.value < NumDays) i diff --git a/nbri_ehr/resources/queries/nbri_ehr/locationTypes/.qview.xml b/nbri_ehr/resources/queries/nbri_ehr/locationTypes/.qview.xml new file mode 100644 index 0000000..b1d4016 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/locationTypes/.qview.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/locations.query.xml b/nbri_ehr/resources/queries/nbri_ehr/locations.query.xml new file mode 100644 index 0000000..3f4fe51 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/locations.query.xml @@ -0,0 +1,19 @@ + + + + + + + Location Type + + nbri_ehr + locationTypes + locationTypeId + name + + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/nbri_ehr/locations/.qview.xml b/nbri_ehr/resources/queries/nbri_ehr/locations/.qview.xml new file mode 100644 index 0000000..08af13d --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/locations/.qview.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/locationsMapping.query.xml b/nbri_ehr/resources/queries/nbri_ehr/locationsMapping.query.xml new file mode 100644 index 0000000..d2357c7 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/locationsMapping.query.xml @@ -0,0 +1,28 @@ + + + + + + + Location + + nbri_ehr + locations + locationId + name + + + + Parent Location + + nbri_ehr + locations + locationId + name + + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/nbri_ehr/locationsMapping/.qview.xml b/nbri_ehr/resources/queries/nbri_ehr/locationsMapping/.qview.xml new file mode 100644 index 0000000..6496f3b --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/locationsMapping/.qview.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/necropsyTasks.query.xml b/nbri_ehr/resources/queries/nbri_ehr/necropsyTasks.query.xml new file mode 100644 index 0000000..578d354 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/necropsyTasks.query.xml @@ -0,0 +1,28 @@ + + + + + + Necropsies + + + + + + + + FBEC5D + + + + + + FBEC5D + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/necropsyTasks.sql b/nbri_ehr/resources/queries/nbri_ehr/necropsyTasks.sql new file mode 100644 index 0000000..d7efcf4 --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/necropsyTasks.sql @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + t.taskid, + d.Id AS animalId, + t.updateTitle AS form, + t.assignedTo, + t.created, + t.createdBy, + t.modified, + t.modifiedBy, + CASE WHEN t.qcstate.Label = 'Request: Pending' THEN 'Death Entered: Necropsy Pending' + WHEN t.qcstate.Label = 'Review Required' THEN 'Necropsy Entered: Review Required' + ELSE t.qcstate.Label + END AS status, + CASE WHEN t.qcstate.Label = 'Request: Pending' THEN 1 + WHEN t.qcstate.Label = 'Review Required' THEN 2 + WHEN t.qcstate.Label = 'Completed' THEN 3 + ELSE 4 + END AS statusOrder +FROM ehr.tasks t +LEFT JOIN study.deaths d ON d.taskid = t.taskid +WHERE formType = 'Necropsy' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/necropsyTasks/.qview.xml b/nbri_ehr/resources/queries/nbri_ehr/necropsyTasks/.qview.xml new file mode 100644 index 0000000..908527e --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/necropsyTasks/.qview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/staff.query.xml b/nbri_ehr/resources/queries/nbri_ehr/staff.query.xml new file mode 100644 index 0000000..c39c37c --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/staff.query.xml @@ -0,0 +1,128 @@ + + + + + Staff + + + First Name + + + Last Name + + + Middle Name + + + Display Name + + + Hire Date + + + Last Employ Date + + + Office Phone + + + Office Phone Ext + + + Office Fax + + + Home Phone + + + Beeper Phone + + + Cell Phone + + + Emergency Contact + + + Emergency Phone + + + Home Address 1 + + + Home Address2 + + + Home City + + + Home State + + + Home Zip + + + Home Zip Ext + + + Home Country + + + Office Address 1 + + + Office Address 2 + + + Office City + + + Office State + + + Office Zip + + + Office Zip Ext + + + Office Country + + + Birth Date + + + High School Name + + + College Grad Date + + + College Degree + + + College Major + + + College Name + + + Supervisor + + nbri_ehr + staff + staffId + displayName + + + + Position Name + + + Position Description + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/nbri_ehr/stress.query.xml b/nbri_ehr/resources/queries/nbri_ehr/stress.query.xml new file mode 100644 index 0000000..590673d --- /dev/null +++ b/nbri_ehr/resources/queries/nbri_ehr/stress.query.xml @@ -0,0 +1,20 @@ + + + + + Stress Levels + + + Regulatory Stress Level + + ehr_lookups + regulatory_stress_levels + value + title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/AcquisitionReport.sql b/nbri_ehr/resources/queries/study/AcquisitionReport.sql new file mode 100644 index 0000000..0f86bec --- /dev/null +++ b/nbri_ehr/resources/queries/study/AcquisitionReport.sql @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT d.Id, + d.gender, + d.species, + d.Birth, + d.Id.MostRecentArrival.Center_Arrival, + cpp.project +FROM study.demographics d + LEFT JOIN CurrentProtocolProjectReport cpp ON cpp.Id = d.Id +ORDER BY d.Id ASC \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/AcquisitionReportBySpecies.sql b/nbri_ehr/resources/queries/study/AcquisitionReportBySpecies.sql new file mode 100644 index 0000000..03dbac6 --- /dev/null +++ b/nbri_ehr/resources/queries/study/AcquisitionReportBySpecies.sql @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +PARAMETERS(StartDate TIMESTAMP, EndDate TIMESTAMP, Project VARCHAR) + +SELECT s.species, s.project, s.speciesName, COUNT(*) as Total FROM + ( + SELECT + species, + species.scientific_name AS speciesName, + Center_Arrival, + project + FROM study.AcquisitionReport ar + WHERE CAST(COALESCE(StartDate, '1900-01-01') as date) <= ar.Center_Arrival AND CAST(COALESCE(EndDate, curdate()) as date) >= CAST(ar.Center_Arrival as date) AND Project = ar.project + ) s +GROUP BY s.species, s.project, s.speciesName \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/BehaviorClinRemarks.sql b/nbri_ehr/resources/queries/study/BehaviorClinRemarks.sql new file mode 100644 index 0000000..fc13d3f --- /dev/null +++ b/nbri_ehr/resources/queries/study/BehaviorClinRemarks.sql @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT * FROM study.clinremarks +WHERE category = 'Behavior' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/BehaviorClinRemarks/.qview.xml b/nbri_ehr/resources/queries/study/BehaviorClinRemarks/.qview.xml new file mode 100644 index 0000000..4e381e4 --- /dev/null +++ b/nbri_ehr/resources/queries/study/BehaviorClinRemarks/.qview.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/ClinicalClinRemarks.sql b/nbri_ehr/resources/queries/study/ClinicalClinRemarks.sql new file mode 100644 index 0000000..67cbaa1 --- /dev/null +++ b/nbri_ehr/resources/queries/study/ClinicalClinRemarks.sql @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT * FROM study.clinremarks +WHERE category = 'Clinical' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/ClinicalClinRemarks/.qview.xml b/nbri_ehr/resources/queries/study/ClinicalClinRemarks/.qview.xml new file mode 100644 index 0000000..c3ca1ea --- /dev/null +++ b/nbri_ehr/resources/queries/study/ClinicalClinRemarks/.qview.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/CurrentProtocolProjectReport.sql b/nbri_ehr/resources/queries/study/CurrentProtocolProjectReport.sql new file mode 100644 index 0000000..c8478fb --- /dev/null +++ b/nbri_ehr/resources/queries/study/CurrentProtocolProjectReport.sql @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +SELECT DISTINCT Id, protocol.title as protocol, project FROM + ( + SELECT DISTINCT d.Id, + a.project.name as project, a.enddate AS projectenddate, + pa.protocol, pa.enddate AS protocolenddate + FROM study.demographics d + JOIN study.assignment a ON a.Id = d.Id + JOIN study.protocolAssignment pa ON pa.Id = d.Id + WHERE a.enddate IS NULL + ) sub +WHERE sub.protocolenddate IS NULL \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/MHC.js b/nbri_ehr/resources/queries/study/MHC.js new file mode 100644 index 0000000..334a25c --- /dev/null +++ b/nbri_ehr/resources/queries/study/MHC.js @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/MHC.query.xml b/nbri_ehr/resources/queries/study/MHC.query.xml new file mode 100644 index 0000000..c513a9e --- /dev/null +++ b/nbri_ehr/resources/queries/study/MHC.query.xml @@ -0,0 +1,14 @@ + + + + + + + false + false + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/Pedigree.sql b/nbri_ehr/resources/queries/study/Pedigree.sql new file mode 100644 index 0000000..331c8bd --- /dev/null +++ b/nbri_ehr/resources/queries/study/Pedigree.sql @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + + d.id as Id, + d.dam as Dam, + d.sire as Sire, + d.modified, + + CASE (d.id.demographics.gender.meaning) + WHEN 'male' THEN 1 + WHEN 'female' THEN 2 + ELSE 3 + END AS gender, + d.id.demographics.gender.meaning as gender_code, + CASE (d.id.demographics.calculated_status) + WHEN 'Alive' THEN 0 + ELSE 1 + END + AS status, + d.id.demographics.calculated_status as status_code, + d.id.demographics.species.common_name as species, + '' as Display, + 'Demographics' as source, + d.modified + +FROM study.demographics d +WHERE d.Dam IS NOT NULL OR d.Sire IS NOT NULL diff --git a/nbri_ehr/resources/queries/study/Weight.js b/nbri_ehr/resources/queries/study/Weight.js new file mode 100644 index 0000000..b8bfa8c --- /dev/null +++ b/nbri_ehr/resources/queries/study/Weight.js @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); + +function onInit(event, helper){ + helper.decodeExtraContextProperty('skipIdNotFoundError'); + + if (helper.getProperty('skipIdNotFoundError')['form'] === 'arrival'|| + helper.getProperty('skipIdNotFoundError')['form'] === 'birth') { + helper.setScriptOptions({ + allowAnyId: true + }); + } + + helper.registerRowProcessor(function(helper, row){ + if (!row) + return; + + if (!row.Id || !row.weight){ + return; + } + + var weightInTransaction = helper.getProperty('weightInTransaction'); + weightInTransaction = weightInTransaction || {}; + weightInTransaction[row.Id] = weightInTransaction[row.Id] || []; + + var shouldAdd = true; + if (row.objectid){ + LABKEY.ExtAdapter.each(weightInTransaction[row.Id], function(r){ + if (r.objectid == row.objectid){ + if (r.weight != row.weight){ + r.weight = row.weight; + } + else { + shouldAdd = false; + return false; + } + } + }, this); + } + + if (shouldAdd){ + weightInTransaction[row.Id].push({ + objectid: row.objectid, + date: row.date, + qcstate: row.QCState, + weight: row.weight + }); + } + + helper.setProperty('weightInTransaction', weightInTransaction); + }); +} + +function onUpsert(helper, scriptErrors, row, oldRow){ + if (!row.weight){ + EHR.Server.Utils.addError(scriptErrors, 'weight', 'This field is required', 'WARN'); + } + + // warn if more than 10% different from last weight + // the highest error this can produce is WARN. therefore skip this check if we would ignore it anyway in order to save the overhead. + // this would normally occur when finalizing a form + if (!helper.isETL() && row.Id && row.weight && EHR.Server.Utils.shouldIncludeError('WARN', helper.getErrorThreshold(), helper)){ + EHR.Server.Utils.findDemographics({ + participant: row.Id, + helper: helper, + scope: this, + callback: function(data){ + if (!data) + return; + + if (data.mostRecentWeight && (row.weight <= data.mostRecentWeight * 0.9)){ + EHR.Server.Utils.addError(scriptErrors, 'weight', 'Weight drop of >10%. Last weight ' + data.mostRecentWeight + ' kg', 'INFO'); + } + else if (data.mostRecentWeight && (row.weight >= data.mostRecentWeight / 0.9)){ + EHR.Server.Utils.addError(scriptErrors, 'weight', 'Weight gain of >10%. Last weight ' + data.mostRecentWeight + ' kg', 'INFO'); + } + + if (data && data.species){ + var msg = helper.getJavaHelper().verifyWeightRange(row.id, row.weight, data.species); + if (msg != null){ + EHR.Server.Utils.addError(scriptErrors, 'weight', msg, 'WARN'); + } + } + } + }); + } +} \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/activeAssignments.sql b/nbri_ehr/resources/queries/study/activeAssignments.sql new file mode 100644 index 0000000..990598c --- /dev/null +++ b/nbri_ehr/resources/queries/study/activeAssignments.sql @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT pa.Id, + pa.protocol.title AS protocolTitle, + pa.protocol.InvestigatorId AS investigatorId, + pa.protocol.InvestigatorId.DisplayName AS investigatorName, + pa.protocol.InvestigatorId.LastName AS investigatorLastName, + a.project.name AS project, + a.isActive AS isActiveAssignment, + pa.isActive AS isActiveProtocolAssignment, + a.qcstate.publicData AS isPublicAssignment, + pa.qcstate.publicData AS isPublicProtocolAssignment + + FROM protocolAssignment pa +FULL OUTER JOIN assignment a ON pa.Id = a.Id +WHERE pa.isActive = true AND + a.isActive = true AND + a.qcstate.publicData = true AND + pa.qcstate.publicData = true diff --git a/nbri_ehr/resources/queries/study/activeBehaviorCases.sql b/nbri_ehr/resources/queries/study/activeBehaviorCases.sql new file mode 100644 index 0000000..cbaf73f --- /dev/null +++ b/nbri_ehr/resources/queries/study/activeBehaviorCases.sql @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT * FROM study.cases +WHERE category = 'Behavior' AND isOpen = TRUE \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/activeBehaviorCases/.qview.xml b/nbri_ehr/resources/queries/study/activeBehaviorCases/.qview.xml new file mode 100644 index 0000000..b08797c --- /dev/null +++ b/nbri_ehr/resources/queries/study/activeBehaviorCases/.qview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/activeClinicalCases.sql b/nbri_ehr/resources/queries/study/activeClinicalCases.sql new file mode 100644 index 0000000..1115b1e --- /dev/null +++ b/nbri_ehr/resources/queries/study/activeClinicalCases.sql @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT * FROM study.cases +WHERE category = 'Clinical' AND isOpen = TRUE \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/activeClinicalCases/.qview.xml b/nbri_ehr/resources/queries/study/activeClinicalCases/.qview.xml new file mode 100644 index 0000000..b08797c --- /dev/null +++ b/nbri_ehr/resources/queries/study/activeClinicalCases/.qview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/activeProjectsFromHousing.sql b/nbri_ehr/resources/queries/study/activeProjectsFromHousing.sql new file mode 100644 index 0000000..e3af892 --- /dev/null +++ b/nbri_ehr/resources/queries/study/activeProjectsFromHousing.sql @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + Id.activeProjectAssignments.project, + COUNT(*) as Total +FROM housing +GROUP BY Id.activeProjectAssignments.project \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/activeTreatmentOrders.sql b/nbri_ehr/resources/queries/study/activeTreatmentOrders.sql new file mode 100644 index 0000000..a243913 --- /dev/null +++ b/nbri_ehr/resources/queries/study/activeTreatmentOrders.sql @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + Id, + date, + enddate, + code, + frequency, + route, + volume, + vol_units, + amount, + amount_units, + concentration, + conc_units, + dosage, + dosage_units, + performedBy, + description, + remark +FROM treatment_order +WHERE enddate IS NULL OR enddate >= NOW() -- calculated col. isActive is false when the enddate is in the future, so using this condition instead \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/alias.js b/nbri_ehr/resources/queries/study/alias.js new file mode 100644 index 0000000..e9f0b13 --- /dev/null +++ b/nbri_ehr/resources/queries/study/alias.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/alias.query.xml b/nbri_ehr/resources/queries/study/alias.query.xml new file mode 100644 index 0000000..c67c110 --- /dev/null +++ b/nbri_ehr/resources/queries/study/alias.query.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + Type + + ehr_lookups + alias_category + value + title + + + + Alias + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/aliases.sql b/nbri_ehr/resources/queries/study/aliases.sql new file mode 100644 index 0000000..a1b279f --- /dev/null +++ b/nbri_ehr/resources/queries/study/aliases.sql @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +-- This query is used to match upper and lowercase names in animal history + +SELECT Id, + Id as alias +FROM study.Animal where Dataset.Demographics.calculated_status != 'Alive - In Progress' +UNION +SELECT Id, + Name as alias +FROM nbri_ehr.IdHistory +UNION +SELECT Id, + Alias as alias +FROM study.alias where Id.demographics.calculated_status != 'Alive - In Progress' +' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/alopecia/.qview.xml b/nbri_ehr/resources/queries/study/alopecia/.qview.xml new file mode 100644 index 0000000..f889f92 --- /dev/null +++ b/nbri_ehr/resources/queries/study/alopecia/.qview.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/arrival.js b/nbri_ehr/resources/queries/study/arrival.js new file mode 100644 index 0000000..251c651 --- /dev/null +++ b/nbri_ehr/resources/queries/study/arrival.js @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_UPSERT, 'study', 'Arrival', function(helper, scriptErrors, row, oldRow) { + + if(!row.rearrival){ + helper.setScriptOptions({requiresStatusRecalc: true}); + } + + // Due to order of operation, this needs to be done in upsert instead of insert + if (!row.rearrival && helper.getEvent() == 'insert' && row.Id && triggerHelper.animalIdExists(row.Id)) { + EHR.Server.Utils.addError(scriptErrors, 'Id', 'Animal Id ' + row.Id + ' is already in use. Please use a different Id.', 'ERROR'); + } + + if (row.eventDate) { + row.date = row.eventDate; + } + + helper.registerArrival(row.Id, row.date); + + //Insert or update demographic and birth records + if (!row.rearrival && !helper.isETL() && !helper.isGeneratedByServer() && !helper.isValidateOnly()) { + + // this allows demographic records in qcstates other than completed + var extraDemographicsFieldMappings = { + 'taskid': row.taskid, + 'qcstate': helper.getJavaHelper().getQCStateForLabel(row.QCStateLabel).getRowId() + } + + // null (not undefined) required for call to java trigger helper + row.dam = row['Id/demographics/dam'] || null; + row.sire = row['Id/demographics/sire'] || null; + row.species = row['Id/demographics/species'] || null; + row.birth = row['Id/demographics/birth'] || null; + row.gender = row['Id/demographics/gender'] || null; + row.geographic_origin = row['Id/demographics/geographic_origin'] || null; + row.source = row.sourceFacility || null; + + if (row.QCStateLabel) { + row.qcstate = helper.getJavaHelper().getQCStateForLabel(row.QCStateLabel).getRowId(); + } + + if (row.birth) { + var birthInfo = { + Id: row.Id, + date: row.birth, + qcstate: row.qcstate, + taskid: row.taskid, + performedby: row.performedby + } + + var birthErrors = triggerHelper.saveBirthRecord(row.Id, birthInfo); + if (birthErrors){ + EHR.Server.Utils.addError(scriptErrors, 'birth', birthErrors, 'ERROR'); + } + } + + if (row.Id && row.date) { + + let assignmentRec = { + Id: row.Id, + date: row.date, + taskid: row.taskid, + remark: row.remark, + qcstate: row.qcstate, + performedby: row.performedby + } + + if (row.project) { + assignmentRec['project'] = row.project; + triggerHelper.createAssignmentRecord("assignment", row.Id, assignmentRec); + } + + if (row.arrivalProtocol) { + assignmentRec['protocol'] = row.arrivalProtocol; + triggerHelper.createAssignmentRecord("protocolAssignment", row.Id, assignmentRec); + } + } + + // if 'cage', labeled as "Initial Location" is provided, then insert into housing. + if (row.cage && row.Id && row.date) { + var housingRec = { + Id: row.Id, + date: row.date, + cage: row.cage, + taskid: row.taskid, + qcstate: row.qcstate, + reason: row.arrivalType, + performedby: row.performedby + } + + var housingErrors = triggerHelper.createHousingRecord(row.Id, housingRec, "arrival"); + if (housingErrors) { + EHR.Server.Utils.addError(scriptErrors, 'Id', housingErrors, 'ERROR'); + } + } + + row.calculated_status = (row.QCStateLabel.toUpperCase() === 'IN PROGRESS' || row.QCStateLabel.toUpperCase() === 'REVIEW REQUIRED') ? 'Alive - In Progress' : 'Alive'; + + if(!oldRow) { + //if not already present, insert into demographics + helper.getJavaHelper().createDemographicsRecord(row.Id, row, extraDemographicsFieldMappings); + } + else { + //Update demographics records + var ar = helper.getJavaHelper().getDemographicRecord(row.id); + var data = ar || {}; + + var obj = {}; + var hasUpdates = false; + + if (row.gender && row.gender !== data.gender ) + { + obj.gender = row.gender; + hasUpdates = true; + } + + if (row.species && row.species !== data.species ) + { + obj.species = row.species; + hasUpdates = true; + } + + if (row.geographic_origin && row.geographic_origin !== data.geographic_origin ) + { + obj.geographic_origin = row.geographic_origin; + hasUpdates = true; + } + + if (row.birth && row.birth !== data.birth) + { + obj.birth = row.birth; + hasUpdates = true; + } + + if (row.sire && row.sire !== data.sire) + { + obj.sire = row.sire; + hasUpdates = true; + } + + if (row.dam && row.dam !== data.dam) + { + obj.dam = row.dam; + hasUpdates = true; + } + + if (row.QCStateLabel && row.QCStateLabel !== data.QCStateLabel) + { + obj.QCStateLabel = row.QCStateLabel; + hasUpdates = true; + } + + if (row.performedby && row.performedby !== data.performedby) + { + obj.performedby = row.performedby; + hasUpdates = true; + } + + if (hasUpdates) + { + console.info("Arrival update for animal Id " + row.Id + " included demographic changes Demographic record updated."); + obj.Id = row.Id; + var demographicsUpdates = [obj]; + helper.getJavaHelper().updateDemographicsRecord(demographicsUpdates); + helper.cacheDemographics(row.Id, row); + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/arrival.query.xml b/nbri_ehr/resources/queries/study/arrival.query.xml new file mode 100644 index 0000000..ffe2108 --- /dev/null +++ b/nbri_ehr/resources/queries/study/arrival.query.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + Arrival Date + + + Arrival Type + + ehr_lookups + arrival_type + value + + + + Acquisition Type + + ehr_lookups + acquisition_type + value + + + + true + + + 80 + Initial Location + true + true + + ehr_lookups + cage + location + cage + + + + Project + + ehr + project + project + name + + + + Protocol + + ehr + protocol + protocol + title + + + + Source Facility + + ehr_lookups + source + meaning + + + + Rearrival + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/arrival/.qview.xml b/nbri_ehr/resources/queries/study/arrival/.qview.xml new file mode 100644 index 0000000..9aa2dd4 --- /dev/null +++ b/nbri_ehr/resources/queries/study/arrival/.qview.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/assignment.js b/nbri_ehr/resources/queries/study/assignment.js new file mode 100644 index 0000000..d35e461 --- /dev/null +++ b/nbri_ehr/resources/queries/study/assignment.js @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); +var projectData = {}; +var prevAnimalId; +var prevDate; +var count = 0; + +function getLastAssignment(id){ + var batchLatestEnddate; + + LABKEY.Query.selectRows({ + schemaName: 'study', + queryName: 'assignment', + columns: 'Id,enddate', + filterArray: [LABKEY.Filter.create('Id', id)], + sort: '-enddate', + success: function (results) { + if (results.rows.length) { + batchLatestEnddate = results.rows[0].enddate; + } + }, + scope: this + }); + + return batchLatestEnddate; +} + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'assignment', function(event, helper){ + + if (helper.isETL()) { + LABKEY.Query.selectRows({ + schemaName: 'ehr', + queryName: 'project', + columns: 'project,name', + success: function (results) { + if (results.rows.length) { + for (var i = 0; i < results.rows.length; i++) { + let rec = results.rows[i]; + projectData[rec.name] = rec.project; + } + } + }, + scope: this + }); + } +}); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_INSERT, 'study', 'assignment', function (helper, scriptErrors, row, oldRow) { + + if (helper.isETL()) { + if (prevAnimalId === row.Id) { + row.date = prevDate; + } + else if (count === 0) { + // This handles batch boundary row for full truncate ETL, which is the only ETL setup for this currently. + // Gets previous enddate from db for first row + var batchLatestEnddate = getLastAssignment(row.Id); + if (batchLatestEnddate) { + row.date = batchLatestEnddate; + } + } + + if (!row.projectName) { + console.log("project name is missing for Id: " + row.Id); + } + else { + var projectName = row.projectName.split(' ' + row.Id)[0]; + var projectId = projectData[projectName]; + + if (projectId) { + row.project = projectId; + } + else { + row.description = projectName; + console.log("project cannot be found: " + projectName + " for Id: " + row.Id); + } + } + prevAnimalId = row.Id; + if (!(!row.endDate || row.endDate === 'undefined')) { + prevDate = row.endDate; + } + + count++; + } + +}); + diff --git a/nbri_ehr/resources/queries/study/assignment.query.xml b/nbri_ehr/resources/queries/study/assignment.query.xml new file mode 100644 index 0000000..1cf7a36 --- /dev/null +++ b/nbri_ehr/resources/queries/study/assignment.query.xml @@ -0,0 +1,28 @@ + + + + + + + + DateTime + + + + + ehr + project + project + name + + + + + + true + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/behaviorCases.sql b/nbri_ehr/resources/queries/study/behaviorCases.sql new file mode 100644 index 0000000..da9e9d8 --- /dev/null +++ b/nbri_ehr/resources/queries/study/behaviorCases.sql @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT * FROM study.cases +WHERE category = 'Behavior' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/behaviorCases/.qview.xml b/nbri_ehr/resources/queries/study/behaviorCases/.qview.xml new file mode 100644 index 0000000..b08797c --- /dev/null +++ b/nbri_ehr/resources/queries/study/behaviorCases/.qview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/behaviorObservations.sql b/nbri_ehr/resources/queries/study/behaviorObservations.sql new file mode 100644 index 0000000..3cedb8c --- /dev/null +++ b/nbri_ehr/resources/queries/study/behaviorObservations.sql @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT * FROM study.clinical_observations +WHERE type = 'Behavior' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/behaviorObservations/.qview.xml b/nbri_ehr/resources/queries/study/behaviorObservations/.qview.xml new file mode 100644 index 0000000..a48d5a5 --- /dev/null +++ b/nbri_ehr/resources/queries/study/behaviorObservations/.qview.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/birth.js b/nbri_ehr/resources/queries/study/birth.js new file mode 100644 index 0000000..aefe06a --- /dev/null +++ b/nbri_ehr/resources/queries/study/birth.js @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); +EHR.Server.Utils = require("ehr/utils").EHR.Server.Utils; + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +function onInit(event, helper){ + helper.setScriptOptions({ + allowAnyId: true, + requiresStatusRecalc: true, + allowDeadIds: true, + skipIdFormatCheck: true, + skipHousingCheck: true, + announceAllModifiedParticipants: true, + allowDatesInDistantPast: true, + removeTimeFromDate: true, + skipAssignmentCheck: true, + }); + + helper.decodeExtraContextProperty('birthsInTransaction'); +} + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_UPSERT, 'study', 'birth', function(helper, scriptErrors, row, oldRow) { + + if (!oldRow && row.Id && triggerHelper.birthExists(row.Id)) { + EHR.Server.Utils.addError(scriptErrors, 'Id', 'Birth record already exists for this Id, update existing record to change birth information', 'ERROR'); + } + + if (!helper.isETL()) { + + if (row.QCStateLabel) { + row.qcstate = helper.getJavaHelper().getQCStateForLabel(row.QCStateLabel).getRowId(); + } + + if (row.Id && row.date) { + + let assignmentRec = { + Id: row.Id, + date: row.date, + taskid: row.taskid, + remark: row.remark, + qcstate: row.qcstate, + performedby: row.performedby + } + + if (row.project) { + assignmentRec['project'] = row.project; + triggerHelper.createAssignmentRecord("assignment", row.Id, assignmentRec); + } + + if (row.birthProtocol) { + assignmentRec['protocol'] = row.birthProtocol; + triggerHelper.createAssignmentRecord("protocolAssignment", row.Id, assignmentRec); + } + } + + if (!helper.isGeneratedByServer() && !helper.isValidateOnly()) { + + // if 'cage', labeled as "Birth Location" is provided, then insert into housing. + if (row.cage && row.Id && row.date) { + var housingRec = { + Id: row.Id, + date: row.date, + cage: row.cage, + taskid: row.taskid, + qcstate: row.qcstate, + reason: 'Husbandry', + performedby: row.performedby + } + + var housingErrors = triggerHelper.createHousingRecord(row.Id, housingRec, "birth"); + if (housingErrors) { + EHR.Server.Utils.addError(scriptErrors, 'Id', housingErrors, 'ERROR'); + } + } + + // this allows demographic records in qcstates other than completed + var extraDemographicsFieldMappings = { + 'qcstate': helper.getJavaHelper().getQCStateForLabel(row.QCStateLabel).getRowId() + } + + var calc_status = (row.QCStateLabel.toUpperCase() === 'IN PROGRESS' || row.QCStateLabel.toUpperCase() === 'REVIEW REQUIRED') ? 'Alive - In Progress' : 'Alive'; + + var obj = { + Id: row.Id, + date: row.date, + calculated_status: calc_status, + dam: row['Id/demographics/dam'] || null, + sire: row['Id/demographics/sire'] || null, + species: row['Id/demographics/species'] || null, + birth: row.date || null, + gender: row['Id/demographics/gender'] || null, + taskid: row.taskid, + remark: row.remark, + QCStateLabel: row.QCStateLabel, + performedby: row.performedby + }; + + //find dam, if provided + if (obj.dam && !obj.origin) { + obj.origin = helper.getJavaHelper().getGeographicOrigin(obj.dam); + } + + if (obj.dam && !obj.species) { + obj.species = helper.getJavaHelper().getSpecies(obj.dam); + } + + if (!oldRow) { + //if not already present, we insert into demographics + helper.getJavaHelper().createDemographicsRecord(row.Id, obj, extraDemographicsFieldMappings); + } + else { + //Update demographics records + var ar = helper.getJavaHelper().getDemographicRecord(obj.Id); + var data = ar || {}; + + var record = {}; + var hasUpdates = false; + + if (obj.gender && obj.gender !== data.gender) { + record.gender = obj.gender; + hasUpdates = true; + } + + if (obj.species && obj.species !== data.species) { + record.species = obj.species; + hasUpdates = true; + } + + if (obj.birth && obj.birth !== data.birth) { + record.birth = obj.birth; + hasUpdates = true; + } + + if (obj.sire && obj.sire !== data.sire) { + record.sire = obj.sire; + hasUpdates = true; + } + + if (obj.dam && obj.dam !== data.dam) { + record.dam = obj.dam; + hasUpdates = true; + } + + if (obj.performedby && obj.performedby !== data.performedby) { + record.performedby = obj.performedby; + hasUpdates = true; + } + + if (obj.QCStateLabel && obj.QCStateLabel !== data.QCStateLabel) { + record.QCStateLabel = obj.QCStateLabel; + hasUpdates = true; + } + + if (hasUpdates) { + console.info("Birth update for animal Id " + row.Id + " included demographic changes. Demographic record updated."); + record.Id = obj.Id; + var demographicsUpdates = [record]; + helper.getJavaHelper().updateDemographicsRecord(demographicsUpdates); + helper.cacheDemographics(row.Id, row); + } + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/birth.query.xml b/nbri_ehr/resources/queries/study/birth.query.xml new file mode 100644 index 0000000..4084988 --- /dev/null +++ b/nbri_ehr/resources/queries/study/birth.query.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + Birth Date + + + Birth Location + 80 + true + true + + ehr_lookups + cage + location + cage + + + + Project + + ehr + project + project + name + + + + Protocol + + ehr + protocol + protocol + title + + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/blood/.qview.xml b/nbri_ehr/resources/queries/study/blood/.qview.xml new file mode 100644 index 0000000..831d6b5 --- /dev/null +++ b/nbri_ehr/resources/queries/study/blood/.qview.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/bloodDrawChanges.sql b/nbri_ehr/resources/queries/study/bloodDrawChanges.sql new file mode 100644 index 0000000..6ea698a --- /dev/null +++ b/nbri_ehr/resources/queries/study/bloodDrawChanges.sql @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--this query is designed to return any dates when allowable blood draw volume changes +--this includes dates of blood draws, plus the date those draws drop off +PARAMETERS(DATE_INTERVAL INTEGER) + +SELECT + b2.id, + b2.dateOnly, + b2.quantity, + DATE_INTERVAL as blood_draw_interval, + TIMESTAMPADD('SQL_TSI_DAY', (-1 * DATE_INTERVAL), b2.dateOnly) as minDate, + TIMESTAMPADD('SQL_TSI_DAY', DATE_INTERVAL, b2.dateOnly) as maxDate, + +FROM ( + SELECT + b.id, + b.dateOnly, + sum(b.quantity) as quantity + + FROM ( + --find all blood draws within the interval, looking backwards + SELECT + b.id, + b.dateOnly, + b.quantity, + FROM study.blood b + WHERE b.dateOnly > timestampadd('SQL_TSI_DAY', -1 * DATE_INTERVAL, curdate()) + + UNION ALL + + --join 1 row for the current date + SELECT + d1.id, + curdate() as dateOnly, + 0 as quantity, + FROM study.demographics d1 + WHERE d1.calculated_status = 'Alive' + + UNION ALL + + --add one row for each date when the draw drops off the record + SELECT + b.id, + timestampadd('SQL_TSI_DAY', DATE_INTERVAL, b.dateOnly), + 0 as quantity, + FROM study.blood b + WHERE timestampadd('SQL_TSI_DAY', DATE_INTERVAL, b.dateOnly) >= timestampadd('SQL_TSI_DAY', -1 * DATE_INTERVAL, curdate()) + + ) b + + GROUP BY b.id, b.dateOnly + ) b2 \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/breeder/.qview.xml b/nbri_ehr/resources/queries/study/breeder/.qview.xml new file mode 100644 index 0000000..448bd0f --- /dev/null +++ b/nbri_ehr/resources/queries/study/breeder/.qview.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/cases.js b/nbri_ehr/resources/queries/study/cases.js new file mode 100644 index 0000000..d995a6a --- /dev/null +++ b/nbri_ehr/resources/queries/study/cases.js @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +const console = require("console"); +require("ehr/triggers").initScript(this); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +function onInit(event, helper) { + helper.decodeExtraContextProperty('ordersInTransaction'); +} + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_UPSERT, 'study', 'cases', function(helper, errors, row, oldRow){ + if (!helper.isETL()) { + var error = false; + if (row.enddate) { + if (!row.closeRemark) { + EHR.Server.Utils.addError(errors, 'closeRemark', 'Close remark required when closing a case.', 'ERROR'); + error = true; + } + + if(!triggerHelper.canCloseCase()) { + EHR.Server.Utils.addError(errors, 'enddate', 'Veterinarian permission required to close a case.', 'ERROR'); + error = true; + } + } + + if (!row.performedby) { + EHR.Server.Utils.addError(errors, 'performedby', 'Opened By is a required field.', 'ERROR'); + error = true; + } + + if (!helper.isValidateOnly() && row.caseid && row.enddate && oldRow && (row.enddate != oldRow.enddate)) { + triggerHelper.closeDailyClinicalObs(row.caseid, row.enddate); + } + + if (!helper.isValidateOnly() && !error) { + var qc; + if (row.QCStateLabel) { + qc = EHR.Server.Security.getQCStateByLabel(row.QCStateLabel); + } + else if (row.QCState) { + qc = EHR.Server.Security.getQCStateByRowId(row.QCState); + } + + if (!qc) { + console.error('Unable to find QCState: ' + row.QCState + '/' + row.QCStateLabel); + } + else { + + // Don't allow taking an existing non-draft case back to draft + if (oldRow && qc.Label == 'In Progress') { + var oldQc = EHR.Server.Security.getQCStateByLabel(oldRow.QCStateLabel); + if (oldQc.Label != 'In Progress') { + EHR.Server.Utils.addError(errors, null, 'Cannot save a draft copy of a case already opened or in review.', 'ERROR'); + } + } else if (row.category == 'Clinical' && (qc.Label == 'Completed' || qc.Label == 'Review Required') && row.caseid && row.Id && row.performedby && row.taskid && !row.enddate) { + var ordersInTransaction = helper.getProperty('ordersInTransaction'); + var oit = []; + if (ordersInTransaction && ordersInTransaction.length) { + oit = ordersInTransaction; + } + triggerHelper.ensureDailyClinicalObservationOrders(row.Id, row.caseid, row.date, row.performedby, qc.RowId, row.taskid, oit); + } + } + } + } +}); diff --git a/nbri_ehr/resources/queries/study/cases.query.xml b/nbri_ehr/resources/queries/study/cases.query.xml new file mode 100644 index 0000000..b2b7762 --- /dev/null +++ b/nbri_ehr/resources/queries/study/cases.query.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + Open Date + + + Close Date + false + + + Problem Area + + ehr_lookups + problem_list_category + value + + + + Problem Subcategory + + ehr_lookups + problem_list_subcategory + value + + + + textarea + 5 + + + Case Plan + textarea + 5 + + + textarea + 5 + + + Opened By + + + Category + true + false + + ehr_lookups + data_category + value + + + + true + + + false + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/cases/.qview.xml b/nbri_ehr/resources/queries/study/cases/.qview.xml new file mode 100644 index 0000000..340d770 --- /dev/null +++ b/nbri_ehr/resources/queries/study/cases/.qview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/cases/Active Behavior Cases.qview.xml b/nbri_ehr/resources/queries/study/cases/Active Behavior Cases.qview.xml new file mode 100644 index 0000000..8333562 --- /dev/null +++ b/nbri_ehr/resources/queries/study/cases/Active Behavior Cases.qview.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/cases/Active Clinical Cases.qview.xml b/nbri_ehr/resources/queries/study/cases/Active Clinical Cases.qview.xml new file mode 100644 index 0000000..6081418 --- /dev/null +++ b/nbri_ehr/resources/queries/study/cases/Active Clinical Cases.qview.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/cases/All Behavior Cases.qview.xml b/nbri_ehr/resources/queries/study/cases/All Behavior Cases.qview.xml new file mode 100644 index 0000000..261b1bb --- /dev/null +++ b/nbri_ehr/resources/queries/study/cases/All Behavior Cases.qview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/cases/All Clinical Cases.qview.xml b/nbri_ehr/resources/queries/study/cases/All Clinical Cases.qview.xml new file mode 100644 index 0000000..73fb0b2 --- /dev/null +++ b/nbri_ehr/resources/queries/study/cases/All Clinical Cases.qview.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/chemistryResults.query.xml b/nbri_ehr/resources/queries/study/chemistryResults.query.xml new file mode 100644 index 0000000..caa0e9e --- /dev/null +++ b/nbri_ehr/resources/queries/study/chemistryResults.query.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + Date + + + Type + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/chemistryResults/.qview.xml b/nbri_ehr/resources/queries/study/chemistryResults/.qview.xml new file mode 100644 index 0000000..02467cb --- /dev/null +++ b/nbri_ehr/resources/queries/study/chemistryResults/.qview.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinicalCases.sql b/nbri_ehr/resources/queries/study/clinicalCases.sql new file mode 100644 index 0000000..5dbc64b --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinicalCases.sql @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT * FROM study.cases +WHERE category = 'Clinical' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinicalCases/.qview.xml b/nbri_ehr/resources/queries/study/clinicalCases/.qview.xml new file mode 100644 index 0000000..b08797c --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinicalCases/.qview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinicalObservations.sql b/nbri_ehr/resources/queries/study/clinicalObservations.sql new file mode 100644 index 0000000..4de105c --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinicalObservations.sql @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT * FROM study.clinical_observations +WHERE type = 'Clinical' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinicalObservations/.qview.xml b/nbri_ehr/resources/queries/study/clinicalObservations/.qview.xml new file mode 100644 index 0000000..7b1fc1a --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinicalObservations/.qview.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinical_observations.js b/nbri_ehr/resources/queries/study/clinical_observations.js new file mode 100644 index 0000000..9e54948 --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinical_observations.js @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +const console = require("console"); +require("ehr/triggers").initScript(this); + +var animalIdCasesMap = {}; +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +function onInit(event, helper) { + helper.decodeExtraContextProperty('orderTasksInTransaction'); + triggerHelper.clearScheduledObsTaskMap(); +} + +function onUpsert(helper, scriptErrors, row, oldRow) { + + if (!helper.isETL() && !helper.isGeneratedByServer()) { + + if (!row.observation && !row.remark) { + EHR.Server.Utils.addError(scriptErrors, 'observation', 'Must enter an observation or remark', 'WARN'); + EHR.Server.Utils.addError(scriptErrors, 'remark', 'Must enter an observation or remark', 'WARN'); + } + + if (row.category === "Verified Id?" && row.observation === "No" && !row.remark) { + EHR.Server.Utils.addError(scriptErrors, 'remark', "You selected 'No' for 'Verified Id?', please enter Remark", "WARN"); + } + + if (row.category === "Daily Enrichment" && row.observation === "Other" && !row.remark) { + EHR.Server.Utils.addError(scriptErrors, 'remark', "You selected 'Other' for 'Daily Enrichment', please enter Remark", "WARN"); + } + + if (row.category === "Alopecia Score" && !row.observation) { + EHR.Server.Utils.addError(scriptErrors, 'observation', "Score required for 'Alopecia Score'.", "WARN"); + } + + if (row.category === "Alopecia Score" && !row.remark) { + EHR.Server.Utils.addError(scriptErrors, 'remark', "Remark required for 'Alopecia Score'.", "WARN"); + } + + var yesRemarkRequired = (row.category === "Self Biting Observed" || row.category === "New Injury Observed" || row.category === "Other Stereotopy" || row.category === "Environmental Change" || row.category === "Special Enrichment"); + if (yesRemarkRequired && row.observation === "Yes" && !row.remark) { + EHR.Server.Utils.addError(scriptErrors, 'remark', "You selected 'Yes' for " + row.category + ", please explain in the Remark", "WARN"); + } + + // Handle scheduled observations + if (!helper.isValidateOnly() && row.scheduledDate) { + var qc; + if (row.QCStateLabel) { + qc = EHR.Server.Security.getQCStateByLabel(row.QCStateLabel); + } + else if (row.QCState) { + qc = EHR.Server.Security.getQCStateByRowId(row.QCState); + } + + if (!qc) { + console.error('Unable to find QCState: ' + row.QCState + '/' + row.QCStateLabel); + } + else { + var orderTasks = helper.getProperty('orderTasksInTransaction'); + if (orderTasks && orderTasks.length > 0) { + var orderData = triggerHelper.handleScheduledObservations(row, qc.RowId, orderTasks[0]); + + if (orderData) { + row.caseId = orderData.caseId; + row.orderid = orderData.orderId; + row.area = orderData.area; + row.type = orderData.type; + row.taskid = orderData.taskId; + } + } + } + } + } +} \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinical_observations.query.xml b/nbri_ehr/resources/queries/study/clinical_observations.query.xml new file mode 100644 index 0000000..7b058cf --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinical_observations.query.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + Category + + + Area + + ehr_lookups + observation_areas + value + + + + Observation/Score + + + Remark + + + Case + + + Performed By + + + Scheduled Date + + + Type + true + + + Order Id + true + + study + observation_order + objectid + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinical_observations/.qview.xml b/nbri_ehr/resources/queries/study/clinical_observations/.qview.xml new file mode 100644 index 0000000..daaa82d --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinical_observations/.qview.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinical_observations/Alopecia Scores.qview.xml b/nbri_ehr/resources/queries/study/clinical_observations/Alopecia Scores.qview.xml new file mode 100644 index 0000000..0a05b82 --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinical_observations/Alopecia Scores.qview.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinical_observations/Behavior.qview.xml b/nbri_ehr/resources/queries/study/clinical_observations/Behavior.qview.xml new file mode 100644 index 0000000..f7566f3 --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinical_observations/Behavior.qview.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinical_observations/Clinical.qview.xml b/nbri_ehr/resources/queries/study/clinical_observations/Clinical.qview.xml new file mode 100644 index 0000000..adf8cf8 --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinical_observations/Clinical.qview.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinical_observationsSummary.sql b/nbri_ehr/resources/queries/study/clinical_observationsSummary.sql new file mode 100644 index 0000000..40fca9d --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinical_observationsSummary.sql @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + Id, + date, + category, + area, + observation, + remark, + performedBy, + scheduledDate, + QCState, + type +FROM clinical_observations +WHERE type = 'Clinical' +GROUP BY + Id, + date, + category, + area, + observation, + remark, + performedBy, + scheduledDate, + QCState, + type \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinical_observationsSummary/.qview.xml b/nbri_ehr/resources/queries/study/clinical_observationsSummary/.qview.xml new file mode 100644 index 0000000..a48d5a5 --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinical_observationsSummary/.qview.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinremarks.js b/nbri_ehr/resources/queries/study/clinremarks.js new file mode 100644 index 0000000..6a4955a --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinremarks.js @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + + +const console = require("console"); +require("ehr/triggers").initScript(this); + +function onInit(event, helper) { + helper.decodeExtraContextProperty('casesInTransaction'); +} + +function onUpsert(helper, scriptErrors, row, oldRow) { + if (!helper.isETL()) { + + var caseMap = helper.getProperty('casesInTransaction'); + var remarkCase = []; + if (caseMap && caseMap[row.Id]){ + remarkCase = caseMap[row.Id]; + } + + var hasCaseEnddate = remarkCase.length > 0 && remarkCase[0].enddate + + if (!row.s && !row.o && !row.a && !row.p && !row.remark && !hasCaseEnddate) { + EHR.Server.Utils.addError(scriptErrors, 'remark', 'Must enter at least one comment', 'WARN'); + EHR.Server.Utils.addError(scriptErrors, 's', 'Must enter at least one comment', 'WARN'); + } + } +} \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinremarks.query.xml b/nbri_ehr/resources/queries/study/clinremarks.query.xml new file mode 100644 index 0000000..a221d11 --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinremarks.query.xml @@ -0,0 +1,63 @@ + + + + + + + + + History + + + Subjective + textarea + ALWAYS_OFF + + + Objective + textarea + ALWAYS_OFF + + + Assessment + textarea + ALWAYS_OFF + + + Plan + textarea + ALWAYS_OFF + + + Category + + ehr_lookups + data_category + value + + + + + textarea + 5 + + + Vet Review + textarea + 5 + true + + + Vet Review Date + Date + true + + + Date + true + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinremarks/.qview.xml b/nbri_ehr/resources/queries/study/clinremarks/.qview.xml new file mode 100644 index 0000000..903f88d --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinremarks/.qview.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinremarks/Behavior.qview.xml b/nbri_ehr/resources/queries/study/clinremarks/Behavior.qview.xml new file mode 100644 index 0000000..24f5a40 --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinremarks/Behavior.qview.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/clinremarks/Clinical.qview.xml b/nbri_ehr/resources/queries/study/clinremarks/Clinical.qview.xml new file mode 100644 index 0000000..6cb3771 --- /dev/null +++ b/nbri_ehr/resources/queries/study/clinremarks/Clinical.qview.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/colonyPopulationByAgeClass.query.xml b/nbri_ehr/resources/queries/study/colonyPopulationByAgeClass.query.xml new file mode 100644 index 0000000..27edcf5 --- /dev/null +++ b/nbri_ehr/resources/queries/study/colonyPopulationByAgeClass.query.xml @@ -0,0 +1,30 @@ + + + + + Population Summary, By Age and Species + + + Species + + ehr_lookups + species_codes + code + common_name + + + + Animal Count + /query/executeQuery.view?schemaName=study& + query.queryName=demographics& + query.species~eq=${species}& + query.gender~eq=${gender}& + query.Id/ageClass/label~eq=${ageclass}& + query.viewName=Alive%2C at Center& + + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/colonyPopulationChange.sql b/nbri_ehr/resources/queries/study/colonyPopulationChange.sql new file mode 100644 index 0000000..82f9c62 --- /dev/null +++ b/nbri_ehr/resources/queries/study/colonyPopulationChange.sql @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +PARAMETERS(StartDate TIMESTAMP, EndDate TIMESTAMP) + +SELECT + T1.id, +-- T1.id.dataset.demographics.species as species, + 'Births' AS Category, + T1.date, + convert(year(T1.date), integer) AS Year + +FROM study.Birth T1 +WHERE T1.date IS NOT NULL +and cast(COALESCE(STARTDATE, '1900-01-01') as date) <= T1.date and cast(COALESCE(ENDDATE, curdate()) as date) >= cast(T1.date as date) + +UNION ALL + +SELECT + T2.id, +-- T2.id.dataset.demographics.species, + 'Arrivals' AS Category, + T2.date, + convert(year(T2.date), INTEGER) AS Year + +FROM study.Arrival T2 +WHERE T2.date IS NOT NULL +AND T2.qcstate.publicdata = true +and cast(COALESCE(STARTDATE, '1900-01-01') as date) <= T2.date and cast(COALESCE(ENDDATE, curdate()) as date) >= cast(T2.date as date) + +UNION ALL + +SELECT + T3.id, +-- T3.id.dataset.demographics.species, + 'Departures' AS Category, + T3.date, + convert(year(T3.date), INTEGER) AS Year + +FROM study.Departure T3 +WHERE T3.date IS NOT NULL +AND T3.qcstate.publicdata = true +and cast(COALESCE(STARTDATE, '1900-01-01') as date) <= T3.date and cast(COALESCE(ENDDATE, curdate()) as date) >= cast(T3.date as date) + +UNION ALL + +SELECT + T4.id, +-- T4.id.dataset.demographics.species, + 'Deaths' AS Category, + T4.date, + convert(year(T4.date), INTEGER) AS Year + +FROM study.Deaths T4 +WHERE T4.date IS NOT NULL +-- and (t4.notAtCenter is null or t4.notAtCenter = false) +and cast(COALESCE(STARTDATE, '1900-01-01') as date) <= T4.date and cast(COALESCE(ENDDATE, curdate()) as date) >= cast(T4.date as date) diff --git a/nbri_ehr/resources/queries/study/colonyPopulationSummary.query.xml b/nbri_ehr/resources/queries/study/colonyPopulationSummary.query.xml new file mode 100644 index 0000000..1005e5d --- /dev/null +++ b/nbri_ehr/resources/queries/study/colonyPopulationSummary.query.xml @@ -0,0 +1,28 @@ + + + + + Population Summary, By Species + + + Species + + ehr_lookups + species_codes + code + common_name + + + + Animal Count + /query/executeQuery.view?schemaName=study& + query.queryName=demographics& + query.species~eq=${species}& + query.viewName=Alive%2C at Center + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/currentBloodDraws.sql b/nbri_ehr/resources/queries/study/currentBloodDraws.sql new file mode 100644 index 0000000..0e2c056 --- /dev/null +++ b/nbri_ehr/resources/queries/study/currentBloodDraws.sql @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +SELECT + t.id, + t.date, + cast(t.quantity as double) as quantity, + t.species, + t.max_draw_pct, + t.blood_draw_interval, + t.blood_per_kg, + t.mostRecentWeight, + t.mostRecentWeightDate, + t.death, + cast(t.allowableBlood as double) as maxAllowableBlood, + cast(t.bloodPrevious as double) as bloodPrevious, + cast((t.allowableBlood - t.bloodPrevious) as double) as allowablePrevious, + + cast(t.bloodFuture as double) as bloodFuture, + cast((t.allowableBlood - t.bloodFuture) as double) as allowableFuture, + + --if the draw is historic, always consider previous draws only. + --otherwise, look both forward and backwards, then take the interval with the highest volume + cast(case + WHEN t.date < curdate() THEN (t.allowableBlood - t.bloodPrevious) + WHEN t.bloodPrevious < t.bloodFuture THEN (t.allowableBlood - t.bloodFuture) + ELSE (t.allowableBlood - t.bloodPrevious) + end as double) as allowableBlood, + t.minDate, + t.maxDate + +FROM ( + + SELECT + bd.id, + bd.dateOnly as date, + bd.quantity, + d.species, + d.death, + d.id.mostRecentWeight.MostRecentWeight, + d.id.mostRecentWeight.MostRecentWeightDate, + d.species.scientific_name.blood_per_kg, + d.species.scientific_name.max_draw_pct, + bd.blood_draw_interval, + (d.id.mostRecentWeight.MostRecentWeight * d.species.scientific_name.blood_per_kg * d.species.scientific_name.max_draw_pct) AS allowableBlood, + bd.minDate, + bd.maxDate, + COALESCE( + (SELECT SUM(coalesce(draws.quantity, 0)) AS _expr + FROM study.blood draws + WHERE draws.id = bd.id + AND draws.dateOnly > bd.minDate + AND draws.dateOnly <= bd.dateOnly + --NOTE: this has been changed to include pending/non-approved draws + AND draws.countsAgainstVolume = true + ), 0) AS BloodPrevious, + + COALESCE( + (SELECT SUM(coalesce(draws.quantity, 0)) AS _expr + FROM study.blood draws + WHERE draws.id = bd.id + AND draws.dateOnly < bd.maxDate + AND draws.dateOnly >= bd.dateOnly + --NOTE: this has been changed to include pending/non-approved draws + AND draws.countsAgainstVolume = true + ), 0) AS BloodFuture + + FROM study.bloodDrawChanges bd + JOIN study.demographics d ON (d.id = bd.id) + + ) t \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/currentproject.sql b/nbri_ehr/resources/queries/study/currentproject.sql new file mode 100644 index 0000000..3ab2cf2 --- /dev/null +++ b/nbri_ehr/resources/queries/study/currentproject.sql @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +-- This query is used to find the current project + +SELECT DISTINCT assignment.Id, +assignment.project +FROM assignment +WHERE assignment.enddate is null \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/deathNotification.sql b/nbri_ehr/resources/queries/study/deathNotification.sql new file mode 100644 index 0000000..86f8800 --- /dev/null +++ b/nbri_ehr/resources/queries/study/deathNotification.sql @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +SELECT + Id, + date, + taskid, + performedBy.DisplayName AS performedBy, + reason.title AS reason +FROM study.deaths \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/deaths.js b/nbri_ehr/resources/queries/study/deaths.js new file mode 100644 index 0000000..79883b4 --- /dev/null +++ b/nbri_ehr/resources/queries/study/deaths.js @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); +var validIds = []; +var idMap = {}; +var deathIdMap = {}; + +function onInit(event, helper){ + + helper.decodeExtraContextProperty('deathsInTransaction'); + + // Cache valid Ids for check on each row + LABKEY.Query.selectRows({ + requiredVersion: 9.1, + schemaName: 'study', + queryName: 'demographics', + columns: ['Id', 'calculated_status', 'QCState/Label'], + scope: this, + success: function (results) { + if (!results || !results.rows || results.rows.length < 1) + return; + + for(var i=0; i < results.rows.length; i++) { + validIds.push(results.rows[i]["Id"]["value"]) + idMap[results.rows[i]["Id"]["value"]] = {calculated_status: results.rows[i]["calculated_status"]["value"], QCStateLabel: results.rows[i]["QCState/Label"]["value"]}; + // console.log(idMap[results.rows[i]["Id"]["value"]]); + } + }, + failure: function (error) { + console.log("error getting demographics data in death trigger onInit()\n" + error); + } + }); + + LABKEY.Query.selectRows({ + requiredVersion: 9.1, + schemaName: 'study', + queryName: 'deaths', + columns: ['Id', 'QCState/Label'], + scope: this, + success: function (results) { + if (!results || !results.rows || results.rows.length < 1) + return; + + for(var i=0; i < results.rows.length; i++) { + deathIdMap[results.rows[i]["Id"]["value"]] = {QCStateLabel: results.rows[i]["QCState/Label"]["value"]}; + } + }, + failure: function (error) { + console.log("error getting death data in death trigger onInit()\n" + error); + } + }); +} + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.AFTER_DELETE, 'study', 'Deaths', function(helper, errors, row, oldRow) { + + var demographicsUpdates = []; + demographicsUpdates.push({ + Id: row.Id, + death: null, + calculated_status: 'Alive', + QCState: helper.getJavaHelper().getQCStateForLabel('Completed').getRowId(), + }); + + console.log('removing demographics death date for animal:' + row.Id); + helper.getJavaHelper().updateDemographicsRecord(demographicsUpdates); +}); + +function onUpsert(helper, scriptErrors, row, oldRow) { + + var demographicsUpdates = []; + + if (!helper.isETL()) { + + //skip other checks so that the admins can update a death record + if (helper.getEvent() === 'update' && LABKEY.Security.currentUser.isAdmin) { + return; + } + + //only allow death record to be created if the animal is in the demographics table + if (idMap[row.Id]) { + + // check if a death record already exists for this animal + if (idMap[row.Id].calculated_status.toUpperCase() === 'DEAD' && deathIdMap[row.Id].QCStateLabel.toUpperCase() === 'COMPLETED') { + EHR.Server.Utils.addError(scriptErrors, 'Id', 'Death record already exists for this animal.', 'ERROR'); + } + // check if the animal is at the center + else if (idMap[row.Id].calculated_status.toUpperCase() === 'SHIPPED') { + EHR.Server.Utils.addError(scriptErrors, 'Id', 'Animal is not at the center.', 'ERROR'); + } + // Check if an animal that's being entered is pending any request/review. + // Note 1: When trying to enter a new record for an animal, the QCState = 'IN PROGRESS'. + // Note 2: Upon 'Submit Death', the QCState will get set to 'REQUEST: PENDING', and upon 'Submit Necropsy for Review', + // the QCState will get set to 'Review Required' - this way we can distinguish between the two states in the Death/Necropsy workflow. + // If a user tries to submit a new Death record (identified by QCState = 'IN PROGRESS') for an animal that + // already has a pending request/review status in study.deaths, then below error message will be displayed. + else if (row.QCStateLabel.toUpperCase() === 'IN PROGRESS' && + deathIdMap[row.Id] && deathIdMap[row.Id].QCStateLabel && + (deathIdMap[row.Id].QCStateLabel.toUpperCase() === 'REQUEST: PENDING' || + deathIdMap[row.Id].QCStateLabel.toUpperCase() === 'REVIEW REQUIRED')) { + EHR.Server.Utils.addError(scriptErrors, 'Id', 'Death record is pending review for this animal', 'ERROR'); + } + // if 'Save Draft' record already exists, it doesn't allow to 'Save Draft' or 'Submit Death' + // on the same animal again - throws an error "duplicate key value violates unique constraint" + // So, added this check to allow 'Save Draft' record to be saved only once. + else if (oldRow === undefined && row.QCStateLabel.toUpperCase() === 'IN PROGRESS' && + deathIdMap[row.Id] && deathIdMap[row.Id].QCStateLabel && + deathIdMap[row.Id].QCStateLabel.toUpperCase() === 'IN PROGRESS') { + EHR.Server.Utils.addError(scriptErrors, 'Id', 'Death/Necropsy data entry is in progress for this animal', 'ERROR'); + } + else if (!helper.isValidateOnly() && row.Id && row.date && row.QCStateLabel.toUpperCase() === 'COMPLETED') { + + if (validIds.indexOf(row.id) !== -1) { + + // update demographics + demographicsUpdates.push({ + Id: row.Id, + death: row.date, + calculated_status: 'Dead', + QCState: helper.getJavaHelper().getQCStateForLabel(row.QCStateLabel).getRowId() + }); + + console.log('updating demographics death date for animal: ' + row.Id); + helper.getJavaHelper().updateDemographicsRecord(demographicsUpdates); + console.log('updated demographics death date for animal: ' + row.Id); + } + else { + console.log(row.id + " is not a valid animal id"); + } + } + + if(row.QCStateLabel && EHR.Server.Security.getQCStateByLabel(row.QCStateLabel).PublicData) { + var qcstate = helper.getJavaHelper().getQCStateForLabel(row.QCStateLabel).getRowId(); + + //add/update weight record + var weightRecord = { + Id: row.Id, + date: row.date, + weight: row.deathWeight, + taskid: row.taskid, + qcstate: qcstate, + performedby: row.performedby + }; + triggerHelper.upsertWeightRecord(weightRecord); + } + } + } +} + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.AFTER_INSERT, 'study', 'deaths', function(helper, scriptErrors, row, oldRow) { + helper.registerDeath(row.Id, row.date); + triggerHelper.reportDataChange("study", "deaths", [row.Id]); +}); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.COMPLETE, 'study', 'Deaths', function(event, errors, helper){ + var rows = helper.getRows() || []; + for (var i = 0; i < rows.length; i++) { + var row = rows[i].row; + var oldRow = rows[i].oldRow; + + // Notification will get sent when: + // 1) a brand-new row saved directly as 'Request: Pending' (i.e., when a user clicks 'Submit Death'), or + // 2) a draft death record moving from 'In Progress' to 'Request: Pending'. + if (!helper.isETL() && + row && row.Id && + row.QCStateLabel && + row.QCStateLabel.toUpperCase() === 'REQUEST: PENDING' && + (!oldRow || !oldRow.QCStateLabel || oldRow.QCStateLabel.toUpperCase() === 'IN PROGRESS')) { + console.log("Sending NBRI Death Notification") + triggerHelper.sendDeathNotification(row.Id); + + console.log("Updating Procedure Orders to Completed for Animal: " + row.Id + "") + triggerHelper.updateProcedureOrdersToCompleted([row.Id]); + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/deaths.query.xml b/nbri_ehr/resources/queries/study/deaths.query.xml new file mode 100644 index 0000000..35c2e6a --- /dev/null +++ b/nbri_ehr/resources/queries/study/deaths.query.xml @@ -0,0 +1,34 @@ + + + + + + + + Death Date + + + Disposition + + ehr_lookups + death_reason + value + title + + + + Death Weight (kg) + + + + + true + + + true + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/deaths/.qview.xml b/nbri_ehr/resources/queries/study/deaths/.qview.xml new file mode 100644 index 0000000..fdc063c --- /dev/null +++ b/nbri_ehr/resources/queries/study/deaths/.qview.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographics.js b/nbri_ehr/resources/queries/study/demographics.js new file mode 100644 index 0000000..ea36be3 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographics.js @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +require("ehr/triggers").initScript(this); + +let animalIds = []; + +function onInit(event, helper){ + helper.setScriptOptions({ + allowAnyId: true, + requiresStatusRecalc: false, + allowDatesInDistantPast: true + }); +} + +function onUpsert(helper, scriptErrors, row, oldRow){ + //NOTE: this should be getting set by the birth, death, arrival & departure tables + //ALSO: it should be rare to insert directly into this table. usually this record will be created by inserting into either birth or arrival + if (!row.calculated_status && !helper.isETL()){ + row.calculated_status = helper.getJavaHelper().getCalculatedStatusValue(row.Id); + } + + if (helper.isETL() && row.damSire) { + let damSire = row.damSire.split('DAM:'); + if (damSire.length === 1) { + row.damSire.split('DAM'); + } + + if (damSire.length > 1) { + let damAndSire = damSire[1].split("SIRE:") + if (damAndSire.length === 1) { + row.damSire.split('SIRE'); + } + if (damAndSire[0].trim() === row.Id) + { + console.log(row.Id + " listed as it's own dam") + } + if (damAndSire[0].trim() !== 'UNK' && damAndSire[0].trim() !== row.Id) + row.dam = damAndSire[0].trim(); + + if (damAndSire.length > 1 && damAndSire[1].trim() === row.Id) + { + console.log(row.Id + " listed as it's own sire") + } + if (damAndSire.length > 1 && damAndSire[1].trim() !== 'UNK' && damAndSire[1].trim() !== row.Id) + row.sire = damAndSire[1].trim(); + + if (row.sire === row.dam) { + row.sire = ''; + row.dam = ''; + } + } + } +} diff --git a/nbri_ehr/resources/queries/study/demographics.query.xml b/nbri_ehr/resources/queries/study/demographics.query.xml new file mode 100644 index 0000000..bff3d17 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographics.query.xml @@ -0,0 +1,112 @@ + + + + + + + true + + + Sex + + + Species + + + Date + Birth + /query/executeQuery.view? + schemaName=study& + query.queryName=Birth& + query.Id~eq=${Id} + + + + Date + Death + /query/executeQuery.view? + schemaName=study& + query.queryName=Deaths& + query.Id~eq=${Id} + + + + Dam + + study + animal + id + + /ehr/participantView.view?participantId=${dam} + + + Sire + + study + animal + id + + /ehr/participantView.view?participantId=${sire} + + + Disposition + + ehr_lookups + disposition_codes + value + title + + + + Termination + + ehr_lookups + termination_reason_codes + value + title + + + + Date Weaned + Date + + + Implant Number + + + Vendor Number + + + Active Status + + + Animal Status + + + Lot + + nbri_ehr + Lot + LotId + + + + Origin + + ehr_lookups + geographic_origins + meaning + meaning + + + + Source + + + CITES + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographics/.qview.xml b/nbri_ehr/resources/queries/study/demographics/.qview.xml new file mode 100644 index 0000000..56f1f23 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographics/.qview.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsActiveFlags.sql b/nbri_ehr/resources/queries/study/demographicsActiveFlags.sql new file mode 100644 index 0000000..f61af93 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsActiveFlags.sql @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + f1.Id, + group_concat(DISTINCT f1.flag, chr(10)) as flags + +FROM ( + SELECT + f.Id, + CASE + WHEN f.flag is null THEN null + WHEN f.flag.category IS NULL THEN f.flag.value + ELSE cast((CAST(f.flag.category as varchar(100)) || CAST(': ' as varchar(2)) || CAST(f.flag.value as varchar(100))) as varchar(202)) + END as flag + + FROM study.flags f + WHERE f.isActive = true + + ) f1 + +GROUP BY f1.Id \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsActiveProjectAssignment.sql b/nbri_ehr/resources/queries/study/demographicsActiveProjectAssignment.sql new file mode 100644 index 0000000..8ccdbc8 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsActiveProjectAssignment.sql @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + d.id, + a.project.name as project +FROM study.demographics d +LEFT JOIN study.assignment a ON (a.id = d.id AND a.enddate IS NULL) \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsActiveProtocolAssignment.query.xml b/nbri_ehr/resources/queries/study/demographicsActiveProtocolAssignment.query.xml new file mode 100644 index 0000000..e7d003f --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsActiveProtocolAssignment.query.xml @@ -0,0 +1,29 @@ + + + + + Active Protocol Assignments + + + + Protocol + 100 + + + 180 + + + ALWAYS_OFF + Total Protocols + /query/executeQuery.view?schemaName=study&query.queryName=Assignment&query.id~eq=${id}&query.isActive~eq=true + + + ALWAYS_OFF + # Active Assignments + /query/executeQuery.view?schemaName=study&query.queryName=Assignment&query.id~eq=${id}&query.isActive~eq=true + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsActiveProtocolAssignment.sql b/nbri_ehr/resources/queries/study/demographicsActiveProtocolAssignment.sql new file mode 100644 index 0000000..ddc956d --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsActiveProtocolAssignment.sql @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + d.id, + a.protocol.displayName as protocolDisplayName, + initcap(a.protocol.investigatorId.firstName) ||' '|| initcap(a.protocol.investigatorId.lastName) as investigator, + a.protocol.title as protocolTitle, + a.lsid, + cast(CASE + WHEN a.protocol.investigatorId.lastName IS NOT NULL THEN (a.protocol.investigatorId.lastName || ' - ' || a.protocol.displayName) + ELSE a.protocol.displayName + END as varchar(500)) as protocolString + +FROM study.demographics d +LEFT JOIN study.protocolAssignment a ON (a.id = d.id AND a.enddate IS NULL) \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsAliases.query.xml b/nbri_ehr/resources/queries/study/demographicsAliases.query.xml new file mode 100644 index 0000000..09b31f9 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsAliases.query.xml @@ -0,0 +1,9 @@ + + + + + Animal Aliases +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsAliases.sql b/nbri_ehr/resources/queries/study/demographicsAliases.sql new file mode 100644 index 0000000..f70f03f --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsAliases.sql @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT Id, + GROUP_CONCAT(alias, ', ') alias, + category.title as aliasType +FROM alias +GROUP BY Id, category.title + PIVOT alias BY aliasType IN (SELECT title FROM ehr_lookups.alias_category) \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsCagemates.query.xml b/nbri_ehr/resources/queries/study/demographicsCagemates.query.xml new file mode 100644 index 0000000..c4877dd --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsCagemates.query.xml @@ -0,0 +1,24 @@ + + + + + Animals Per Pairing + + + true + + + false + + + Total Animals In Pairing + /query/executeQuery.view?schemaName=study&query.queryName=Demographics&query.id/numPaired/room~eq=${room}&query.id/numPaired/effectiveCage~eq=${effectiveCage} + + + Category + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsCagemates.sql b/nbri_ehr/resources/queries/study/demographicsCagemates.sql new file mode 100644 index 0000000..b3464b7 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsCagemates.sql @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + d.id, +-- t.room, + t.cage, + t.total, + cast(t.animals as varchar(4000)) as animals + +FROM study.demographics d +LEFT JOIN ( +SELECT + h.id, +-- h.room, + h.cage, + count(distinct h2.id) as total, + group_concat(distinct h2.id, ', ') as animals + +FROM study.housing h + +JOIN study.housing h2 +ON (h2.Id.demographics.calculated_status = 'Alive' + AND (h.cage = h2.cage)) + +WHERE h.enddateTimeCoalesced >= now() +GROUP BY h.id, h.room, h.cage + +) t ON (t.id = d.id) + +WHERE d.calculated_status = 'Alive' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsCurLocation.query.xml b/nbri_ehr/resources/queries/study/demographicsCurLocation.query.xml new file mode 100644 index 0000000..de68430 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsCurLocation.query.xml @@ -0,0 +1,35 @@ + + + + + + + true + true + + + + ehr_lookups + cage + location + + + + + 100 + + + /query/executeQuery.view?schemaName=study& + query.queryName=housing& + query.room~eq=${room}& + query.cage~eq=${cage}& + query.enddate~isblank& + query.sort=Id& + + + + Location +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsCurLocation.sql b/nbri_ehr/resources/queries/study/demographicsCurLocation.sql new file mode 100644 index 0000000..7402989 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsCurLocation.sql @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + +d2.id, + +d2.cage AS Location, + +d2.room.area, + +d2.room, + +d2.cage AS cage, + +ifdefined(d2.cond) as cond, + +d2.date, + +d2.reason, + +d2.remark, + +coalesce(d2.room, '') as room_order, +d2.room_sortValue @hidden, + +coalesce(d2.cage, '') as cage_order, +d2.cage_sortValue @hidden, + +d2.performedBy.displayName AS performedBy + +FROM study.housing d2 + +WHERE d2.enddate IS NULL +AND d2.qcstate.publicdata = true \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsLastProject.query.xml b/nbri_ehr/resources/queries/study/demographicsLastProject.query.xml new file mode 100644 index 0000000..d01971e --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsLastProject.query.xml @@ -0,0 +1,13 @@ + + + + + + + Last Project + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsLastProject.sql b/nbri_ehr/resources/queries/study/demographicsLastProject.sql new file mode 100644 index 0000000..16c6ca7 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsLastProject.sql @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +SELECT + d2.id, + d2.project, + h.enddate as enddate + +FROM study.assignment d2 + JOIN (SELECT id, max(date) as maxDate, max(enddate) as enddate FROM study.assignment h GROUP BY id) h + ON (h.id = d2.id and d2.date = h.maxdate) +WHERE d2.qcstate.publicdata = true \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsLastProtocol.query.xml b/nbri_ehr/resources/queries/study/demographicsLastProtocol.query.xml new file mode 100644 index 0000000..94265b7 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsLastProtocol.query.xml @@ -0,0 +1,13 @@ + + + + + + + Last Protocol + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsLastProtocol.sql b/nbri_ehr/resources/queries/study/demographicsLastProtocol.sql new file mode 100644 index 0000000..ace87a8 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsLastProtocol.sql @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +SELECT + d2.id, + d2.protocol, + h.enddate as enddate + +FROM study.protocolAssignment d2 + JOIN (SELECT id, max(date) as maxDate, max(enddate) as enddate FROM study.protocolAssignment h GROUP BY id) h + ON (h.id = d2.id and d2.date = h.maxdate) +WHERE d2.qcstate.publicdata = true \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/demographicsOffspring.query.xml b/nbri_ehr/resources/queries/study/demographicsOffspring.query.xml new file mode 100644 index 0000000..877be40 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsOffspring.query.xml @@ -0,0 +1,20 @@ + + + + + + + true + + + + study + animal + Id + + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsOffspring.sql b/nbri_ehr/resources/queries/study/demographicsOffspring.sql new file mode 100644 index 0000000..9feda19 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsOffspring.sql @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + + d.id as Id, + d2.id AS Offspring, + d2.birth AS date, +d2.sire, +d2.dam, +d2.gender AS sex, +d.qcstate + +FROM study.Demographics d + + INNER JOIN study.Demographics d2 +ON ((d2.sire = d.id OR d2.dam = d.id) AND d.id != d2.id) + +group by d.id, d2.id, d2.birth, d2.sire, d2.dam, d2.gender, d.qcstate diff --git a/nbri_ehr/resources/queries/study/demographicsParents.query.xml b/nbri_ehr/resources/queries/study/demographicsParents.query.xml new file mode 100644 index 0000000..a151cf1 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsParents.query.xml @@ -0,0 +1,31 @@ + + + + + Parents + + + true + + + + study + animal + id + + + + + study + animal + id + + + + Number of Parents Known + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsParents.sql b/nbri_ehr/resources/queries/study/demographicsParents.sql new file mode 100644 index 0000000..91b6d5c --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsParents.sql @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +SELECT + d.id, + d.dam as dam, + 'Observed' as damType, + d.sire as sire, + 'Observed' as sireType, + CASE + WHEN d.dam IS NOT NULL AND d.sire IS NOT NULL THEN 2 + WHEN d.dam IS NOT NULL OR d.sire IS NOT NULL THEN 1 + ELSE 0 + END as numParents +FROM study.demographics d + +-- TODO: Incorporate fostering? Genetic testing? + diff --git a/nbri_ehr/resources/queries/study/demographicsSiblings.query.xml b/nbri_ehr/resources/queries/study/demographicsSiblings.query.xml new file mode 100644 index 0000000..a97b1d1 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsSiblings.query.xml @@ -0,0 +1,44 @@ + + Siblings of Any Animal + + + + Siblings of Any Animal + + + true + + + + /query/executeQuery.view?schemaName=study& + query.queryName=demographicsSiblings& + query.Id~eq=${Id} + + + + + study + animal + Id + + + + + study + animal + Id + + + + + study + animal + Id + + + + Relationship +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsSiblings.sql b/nbri_ehr/resources/queries/study/demographicsSiblings.sql new file mode 100644 index 0000000..a774aed --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsSiblings.sql @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + + d1.id, + + CASE + WHEN (COALESCE(d1.id.parents.sire, '') = COALESCE(d2.id.parents.sire, '') and COALESCE(d1.id.parents.dam, '') = COALESCE(d2.id.parents.dam, '') AND COALESCE(d1.id.parents.sire, '')!='' AND COALESCE(d1.id.parents.dam, '')!='') + THEN 'Full Sib' + WHEN (COALESCE(d1.id.parents.sire, '') = COALESCE(d2.id.parents.sire, '') AND COALESCE(d1.id.parents.sire, '') != '' AND (COALESCE(d1.id.parents.dam, '') != COALESCE(d2.id.parents.dam, '') OR COALESCE(d1.id.parents.dam, '') = '')) + THEN 'Half-Sib Paternal' + WHEN (COALESCE(d1.id.parents.dam, '') = COALESCE(d2.id.parents.dam, '') AND COALESCE(d1.id.parents.dam, '') != '' AND (COALESCE(d1.id.parents.sire, '') != COALESCE(d2.id.parents.sire, '') OR COALESCE(d1.id.parents.sire, '') = '')) + THEN 'Half-Sib Maternal' + WHEN (COALESCE(d1.id.parents.sire, '') != COALESCE(d2.id.parents.sire, '') and COALESCE(d1.id.parents.dam, '') != COALESCE(d2.id.parents.dam, '')) + THEN 'ERROR' + END AS Relationship, + + d2.id AS Sibling, + + d2.id.parents.dam AS SiblingDam, + d2.id.parents.sire AS SiblingSire, + d1.qcstate + +FROM study.Demographics d1 + +--removed left join + JOIN study.Demographics d2 + ON ((d2.id.parents.sire = d1.id.parents.sire OR d2.id.parents.dam = d1.id.parents.dam) AND d1.id != d2.id) + +WHERE d2.id is not null + +-- ) t + diff --git a/nbri_ehr/resources/queries/study/demographicsSource.query.xml b/nbri_ehr/resources/queries/study/demographicsSource.query.xml new file mode 100644 index 0000000..98ae435 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsSource.query.xml @@ -0,0 +1,17 @@ + + + + + Source + + + Days Since Center Arrival + + + From Center? + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsSource.sql b/nbri_ehr/resources/queries/study/demographicsSource.sql new file mode 100644 index 0000000..9de9dfd --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsSource.sql @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +SELECT + d.Id AS Id, + + T1.mostRecentArrival, + T1.earliestArrival, + d.birth, + coalesce(T1.EarliestArrival, d.birth) as center_Arrival, + timestampdiff('SQL_TSI_DAY', coalesce(T1.EarliestArrival, d.birth), now()) as daysSinceCenterArrival, + + CASE + WHEN T1.EarliestArrival IS NULL AND d.birth IS NOT NULL THEN true + ELSE false + END as fromCenter, + d.source as source, + + CASE + WHEN T1.EarliestArrival IS NULL AND d.birth IS NOT NULL THEN 'Born at NBRI' + WHEN T1.EarliestArrival IS NOT NULL AND T2.sourceFacility IS NOT NULL THEN T2.sourceFacility.meaning + ELSE 'Unknown' + END as type + +FROM study.demographics d + +LEFT JOIN + (select T1.Id, max(T1.date) as MostRecentArrival, min(T1.date) as EarliestArrival FROM study.arrival T1 WHERE T1.qcstate.publicdata = true GROUP BY T1.Id) T1 + ON (T1.Id = d.Id) + +LEFT JOIN study.arrival T2 ON (t2.id = d.id AND t2.date = t1.earliestArrival) + diff --git a/nbri_ehr/resources/queries/study/demographicsTotalOffspring.query.xml b/nbri_ehr/resources/queries/study/demographicsTotalOffspring.query.xml new file mode 100644 index 0000000..d42f72b --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsTotalOffspring.query.xml @@ -0,0 +1,34 @@ + + + + + + + true + true + + + /query/executeQuery.view?schemaName=study& + query.queryName=demographicsOffspring& + query.Id~eq=${Id} + + + + /query/executeQuery.view?schemaName=study& + query.queryName=demographicsOffspring& + query.Offspring/demographics/calculated_status~eq=Alive& + query.Id~eq=${Id} + + + + Earliest Birth + + + Latest Birth + + + TotalOffspring +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsTotalOffspring.sql b/nbri_ehr/resources/queries/study/demographicsTotalOffspring.sql new file mode 100644 index 0000000..0ec7a35 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsTotalOffspring.sql @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + + d.id, + group_concat(DISTINCT d2.id) as Offspring, + count(DISTINCT d2.id) as TotalOffspring, + SUM(CASE WHEN d2.calculated_status = 'Alive' THEN 1 ELSE 0 END) as TotalLivingOffspring, + + min(d2.birth) as earliestBirth, + max(d2.birth) as latestBirth + +FROM study.Demographics d + + JOIN study.Demographics d2 + ON (d.id = d2.id.parents.sire OR d.id = d2.id.parents.dam) + +GROUP BY d.id + +UNION + +SELECT + + d3.id, + NULL as Offspring, + 0 as TotalOffspring, + 0 as TotalLivingOffspring, + + NULL as earliestBirth, + NULL as latestBirth + +FROM study.Demographics d3 + +WHERE (d3.id NOT IN ( + SELECT d4.id.parents.sire FROM study.demographics d4 WHERE (d4.id.parents.sire IS NOT NULL) + UNION + SELECT d4.id.parents.dam FROM study.demographics d4 WHERE (d4.id.parents.dam IS NOT NULL))) + +GROUP BY d3.id diff --git a/nbri_ehr/resources/queries/study/departure.js b/nbri_ehr/resources/queries/study/departure.js new file mode 100644 index 0000000..98dd555 --- /dev/null +++ b/nbri_ehr/resources/queries/study/departure.js @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); +var departures = []; + +function onInit(event, helper){ + helper.setScriptOptions({ + requiresStatusRecalc: false + }); + +} + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.AFTER_INSERT, 'study', 'departure', function(helper, scriptErrors, row, oldRow) { + + if (row.id) { + departures.push(row.id); + } +}); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.COMPLETE, 'study', 'departure', function(event, errors, helper){ + + if (!helper.isETL() && helper.isEHRDataEntry()) { + triggerHelper.updateProcedureOrdersToCompleted(departures); + } +}); + diff --git a/nbri_ehr/resources/queries/study/departure.query.xml b/nbri_ehr/resources/queries/study/departure.query.xml new file mode 100644 index 0000000..19845d1 --- /dev/null +++ b/nbri_ehr/resources/queries/study/departure.query.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + Destination + + ehr_lookups + source + meaning + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/departure/.qview.xml b/nbri_ehr/resources/queries/study/departure/.qview.xml new file mode 100644 index 0000000..31e17cb --- /dev/null +++ b/nbri_ehr/resources/queries/study/departure/.qview.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/drug.js b/nbri_ehr/resources/queries/study/drug.js new file mode 100644 index 0000000..52f4fa7 --- /dev/null +++ b/nbri_ehr/resources/queries/study/drug.js @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +require("ehr/triggers").initScript(this); + +let triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_INSERT, 'study', 'drug', function(helper, scriptErrors, row, oldRow) { + if(row.treatmentid && row.scheduledDate && triggerHelper.isTreatmentOrderEntered(row.treatmentid, row.scheduledDate)) { + EHR.Server.Utils.addError(scriptErrors, 'scheduledDate', 'A treatment has already been entered for this order for this date and time.', 'ERROR'); + } +}); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_UPSERT, 'study', 'drug', function(helper, scriptErrors, row, oldRow) { + // Max reasonable amount warning. Error when the amount is greater than the max reasonable amount + if (row.code) { + let drugFormulary = triggerHelper.getFormularyForDrug(row.code); + if (drugFormulary && drugFormulary.maxAmount && row.amount > drugFormulary.maxAmount) { + EHR.Server.Utils.addError(scriptErrors, 'amount', 'Amount is greater than the maximum reasonable amount: ' + drugFormulary.maxAmount, 'ERROR'); + } + } + if (row.volume && !row.vol_units) { + EHR.Server.Utils.addError(scriptErrors, 'volume', 'Units required for volume.', 'ERROR'); + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/drug.query.xml b/nbri_ehr/resources/queries/study/drug.query.xml new file mode 100644 index 0000000..95051db --- /dev/null +++ b/nbri_ehr/resources/queries/study/drug.query.xml @@ -0,0 +1,111 @@ + + + + + /ehr/drugDetails.view?lsid=${lsid} + + + + + + + + Date + + + Treatment + + ehr_lookups + snomed + code + meaning + + + + Route + + ehr_lookups + routes + route + + + + + Volume + + + Vol Units + + ehr_lookups + volume_units + unit + + + + + Amount + + + Amount Units + + ehr_lookups + amount_units + unit + + + + + Drug Conc + + + Conc Units + + ehr_lookups + conc_units + unit + + + + + Dosage + + + Dosage Units + + ehr_lookups + dosage_units + unit + + + + + Remark + + + Category + + ehr_lookups + data_category + value + + + + + Treatment Id + true + + study + treatment_order + objectid + + + + + + Scheduled Date + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/drug/.qview.xml b/nbri_ehr/resources/queries/study/drug/.qview.xml new file mode 100644 index 0000000..3b72268 --- /dev/null +++ b/nbri_ehr/resources/queries/study/drug/.qview.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/drug/Behavior.qview.xml b/nbri_ehr/resources/queries/study/drug/Behavior.qview.xml new file mode 100644 index 0000000..a9769cb --- /dev/null +++ b/nbri_ehr/resources/queries/study/drug/Behavior.qview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/exemptions.js b/nbri_ehr/resources/queries/study/exemptions.js new file mode 100644 index 0000000..e9f0b13 --- /dev/null +++ b/nbri_ehr/resources/queries/study/exemptions.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/exemptions.query.xml b/nbri_ehr/resources/queries/study/exemptions.query.xml new file mode 100644 index 0000000..db997ae --- /dev/null +++ b/nbri_ehr/resources/queries/study/exemptions.query.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + true + + + Category + false + + ehr_lookups + exemption_category + value + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/exemptions/.qview.xml b/nbri_ehr/resources/queries/study/exemptions/.qview.xml new file mode 100644 index 0000000..7e4278b --- /dev/null +++ b/nbri_ehr/resources/queries/study/exemptions/.qview.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/flags.js b/nbri_ehr/resources/queries/study/flags.js new file mode 100644 index 0000000..e9f0b13 --- /dev/null +++ b/nbri_ehr/resources/queries/study/flags.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/flags.query.xml b/nbri_ehr/resources/queries/study/flags.query.xml new file mode 100644 index 0000000..570a645 --- /dev/null +++ b/nbri_ehr/resources/queries/study/flags.query.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + Animal Id + + + Date Added + + + Date Removed + false + + + Flag + + ehr_lookups + flag_values + objectid + value + + + + Value + true + + + + + true + + + true + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/flags/.qview.xml b/nbri_ehr/resources/queries/study/flags/.qview.xml new file mode 100644 index 0000000..bf12e57 --- /dev/null +++ b/nbri_ehr/resources/queries/study/flags/.qview.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/grossPathology.js b/nbri_ehr/resources/queries/study/grossPathology.js new file mode 100644 index 0000000..e9f0b13 --- /dev/null +++ b/nbri_ehr/resources/queries/study/grossPathology.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/grossPathology.query.xml b/nbri_ehr/resources/queries/study/grossPathology.query.xml new file mode 100644 index 0000000..a7fce7d --- /dev/null +++ b/nbri_ehr/resources/queries/study/grossPathology.query.xml @@ -0,0 +1,41 @@ + + + + + + + Organ Systems Examined + + ehr_lookups + organ_systems + value + + + + Appearance + + ehr_lookups + organ_appearance + value + + + + true + + + true + + + true + + + true + + + true + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/grossPathology/.qview.xml b/nbri_ehr/resources/queries/study/grossPathology/.qview.xml new file mode 100644 index 0000000..798d1da --- /dev/null +++ b/nbri_ehr/resources/queries/study/grossPathology/.qview.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/histopathology.query.xml b/nbri_ehr/resources/queries/study/histopathology.query.xml new file mode 100644 index 0000000..e35e753 --- /dev/null +++ b/nbri_ehr/resources/queries/study/histopathology.query.xml @@ -0,0 +1,16 @@ + + + + + + + Diagnosis + + + Category + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/historicalOther.query.xml b/nbri_ehr/resources/queries/study/historicalOther.query.xml new file mode 100644 index 0000000..37e2754 --- /dev/null +++ b/nbri_ehr/resources/queries/study/historicalOther.query.xml @@ -0,0 +1,13 @@ + + + + + + + Type + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/housing.js b/nbri_ehr/resources/queries/study/housing.js new file mode 100644 index 0000000..320556d --- /dev/null +++ b/nbri_ehr/resources/queries/study/housing.js @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); +var prevAnimalId; +var prevDate; + +let triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); +let animalIds = []; + +function onInit(event, helper){ + helper.setScriptOptions({ + skipHousingCheck: true + }); + + helper.decodeExtraContextProperty('housingInTransaction'); + + helper.registerRowProcessor(function(helper, row){ + if (!row) + return; + + if (!row.Id || !row.room){ + return; + } + + var housingInTransaction = helper.getProperty('housingInTransaction'); + housingInTransaction = housingInTransaction || {}; + housingInTransaction[row.Id] = housingInTransaction[row.Id] || []; + + // this is a failsafe in case the client did not provide housing JSON. it ensures + // the current row is part of housingInTransaction + var shouldAdd = true; + if (row.objectid){ + LABKEY.ExtAdapter.each(housingInTransaction[row.Id], function(r){ + if (r.objectid == row.objectid){ + shouldAdd = false; + return false; + } + }, this); + } + + if (shouldAdd){ + housingInTransaction[row.Id].push({ + objectid: row.objectid, + date: row.date, + enddate: row.enddate, + qcstate: row.QCState, + room: row.room, + cage: row.cage, + divider: row.divider + }); + } + + helper.setProperty('housingInTransaction', housingInTransaction); + }); +} + +function onUpsert(helper, scriptErrors, row, oldRow){ + //verify we dont have 2 opened records for the same ID + if (!helper.isETL() && !row.enddate && row.Id){ + var map = helper.getProperty('housingInTransaction'); + if (map && map[row.Id]){ + var housingRecords = map[row.Id]; + for (var i=0;i 0) { + // Only need boundary rows for batch. Changing batch size on ETL may require change here. Incremental updates + // should update all incoming rows so don't do this. + if (helper.isETL() && updateRows.length > 4000) { + console.log("Batch import: only closing boundary housing record") + updateRows = [updateRows[0]]; + } + var idsToClose = []; + for (var i = 0; i < updateRows.length; i++) { + if (EHR.Server.Security.getQCStateByLabel(updateRows[i].row.QCStateLabel).PublicData && updateRows[i].row.date) { + idsToClose.push({ + Id: updateRows[i].row.Id, + date: EHR.Server.Utils.datetimeToString(updateRows[i].row.date), //stringify to serialize properly + objectid: updateRows[i].row.objectid + }); + if (animalIds.indexOf(updateRows[i].row.Id) === -1) { + animalIds.push(updateRows[i].row.Id); + } + } + } + if (idsToClose.length){ + helper.getJavaHelper().closeHousingRecords(idsToClose); + } + } + } +} + diff --git a/nbri_ehr/resources/queries/study/housing.query.xml b/nbri_ehr/resources/queries/study/housing.query.xml new file mode 100644 index 0000000..eeb5e0d --- /dev/null +++ b/nbri_ehr/resources/queries/study/housing.query.xml @@ -0,0 +1,52 @@ + + + + + + + + In Date + + + true + false + true + true + Out Date + + + Location + /nbri_ehr/cageDetails.view?room=${room}&cage=${cage}& + + ehr_lookups + cage + location + cage + + + + Room + /nbri_ehr/cageDetails.view?room=${room}& + + ehr_lookups + rooms + room + name + + + + Reason For Move + + ehr_lookups + housing_reason + value + + + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/housing/.qview.xml b/nbri_ehr/resources/queries/study/housing/.qview.xml new file mode 100644 index 0000000..bc780a5 --- /dev/null +++ b/nbri_ehr/resources/queries/study/housing/.qview.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/housing/Active Housing.qview.xml b/nbri_ehr/resources/queries/study/housing/Active Housing.qview.xml new file mode 100644 index 0000000..4fc3eeb --- /dev/null +++ b/nbri_ehr/resources/queries/study/housing/Active Housing.qview.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/necropsy.js b/nbri_ehr/resources/queries/study/necropsy.js new file mode 100644 index 0000000..81a5c04 --- /dev/null +++ b/nbri_ehr/resources/queries/study/necropsy.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +var deathIdMap = {}; + +function onInit(event, helper){ + + if (!helper.isETL() && event != 'truncate') { + LABKEY.Query.selectRows({ + requiredVersion: 9.1, + schemaName: 'study', + queryName: 'deaths', + columns: ['Id', 'QCState/Label'], + scope: this, + success: function (results) { + if (!results || !results.rows || results.rows.length < 1) + return; + + for (var i = 0; i < results.rows.length; i++) { + deathIdMap[results.rows[i]["Id"]["value"]] = {QCStateLabel: results.rows[i]["QCState/Label"]["value"]}; + } + }, + failure: function (error) { + console.log("error getting death data in death trigger onInit()\n" + error); + } + }); + } +} + +function onUpsert(helper, scriptErrors, row, oldRow) { + + if (!helper.isETL()) { + + if (deathIdMap[row.Id] && deathIdMap[row.Id].QCStateLabel && + (deathIdMap[row.Id].QCStateLabel.toUpperCase() === 'REQUEST: PENDING' || + deathIdMap[row.Id].QCStateLabel.toUpperCase() === 'REVIEW REQUIRED')) { + + if (!row.specimenCondition) + EHR.Server.Utils.addError(scriptErrors, 'specimenCondition', "'Condition of Specimen' is required", 'ERROR'); + if (!row.physicalCondition) + EHR.Server.Utils.addError(scriptErrors, 'physicalCondition', "'Physical Condition' is required", 'ERROR'); + if (!row.diagnosis) + EHR.Server.Utils.addError(scriptErrors, 'diagnosis', "'Diagnosis' is required", 'ERROR'); + if (!row.grossAbnormalities) + EHR.Server.Utils.addError(scriptErrors, 'grossAbnormalities', "'Gross Abnormalities' is required", 'ERROR'); + if (!row.accessionNumber) + EHR.Server.Utils.addError(scriptErrors, 'accessionNumber', "'Accession Number' is required", 'ERROR'); + } + } +} + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.AFTER_INSERT, 'study', 'necropsy', function(helper, scriptErrors, row, oldRow) { + triggerHelper.reportDataChange("study", "necropsy", [row.Id]); +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/necropsy.query.xml b/nbri_ehr/resources/queries/study/necropsy.query.xml new file mode 100644 index 0000000..35290a8 --- /dev/null +++ b/nbri_ehr/resources/queries/study/necropsy.query.xml @@ -0,0 +1,43 @@ + + + + + + + Exam Date + + + Category + + + Diagnosis + + + + ehr_lookups + necropsy_specimen_condition + value + + + + + ehr_lookups + necropsy_physical_condition + value + + + + true + + + true + + + + true + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/necropsy/.qview.xml b/nbri_ehr/resources/queries/study/necropsy/.qview.xml new file mode 100644 index 0000000..2a4be61 --- /dev/null +++ b/nbri_ehr/resources/queries/study/necropsy/.qview.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/necropsyStatus.sql b/nbri_ehr/resources/queries/study/necropsyStatus.sql new file mode 100644 index 0000000..08b6535 --- /dev/null +++ b/nbri_ehr/resources/queries/study/necropsyStatus.sql @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + demo.Id, + CASE WHEN d.QCState.Label = 'Request: Pending' OR d.QCState.Label = 'Review Required' THEN 'Necropsy Pending' ELSE demo.calculated_status END AS necropsy_status + FROM study.demographics demo +LEFT JOIN study.deaths d ON d.Id = demo.Id \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/nhpTraining.js b/nbri_ehr/resources/queries/study/nhpTraining.js new file mode 100644 index 0000000..e9f0b13 --- /dev/null +++ b/nbri_ehr/resources/queries/study/nhpTraining.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/nhpTraining.query.xml b/nbri_ehr/resources/queries/study/nhpTraining.query.xml new file mode 100644 index 0000000..ecf5a11 --- /dev/null +++ b/nbri_ehr/resources/queries/study/nhpTraining.query.xml @@ -0,0 +1,46 @@ + + + + + Animal Training + + + + + Training Type + + ehr_lookups + nhp_training_type + value + + + + Reason + + ehr_lookups + nhp_training_reason + value + + + + Result + + ehr_lookups + nhp_training_result + value + + + + Training Staff + + + true + + + true + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/notes.js b/nbri_ehr/resources/queries/study/notes.js new file mode 100644 index 0000000..e9f0b13 --- /dev/null +++ b/nbri_ehr/resources/queries/study/notes.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/notes.query.xml b/nbri_ehr/resources/queries/study/notes.query.xml new file mode 100644 index 0000000..e45f321 --- /dev/null +++ b/nbri_ehr/resources/queries/study/notes.query.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + true + + + true + + + Type + true + + + Note + false + + + true + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/notes/.qview.xml b/nbri_ehr/resources/queries/study/notes/.qview.xml new file mode 100644 index 0000000..6cd9bab --- /dev/null +++ b/nbri_ehr/resources/queries/study/notes/.qview.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/notificationAnimalProject.sql b/nbri_ehr/resources/queries/study/notificationAnimalProject.sql new file mode 100644 index 0000000..8661a32 --- /dev/null +++ b/nbri_ehr/resources/queries/study/notificationAnimalProject.sql @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +-- Add more here to make a single query for animal details in notifications +SELECT + Id, + date, + project.name AS project, + enddate +FROM study.assignment +WHERE enddate IS NULL \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observationOrdersByDate.sql b/nbri_ehr/resources/queries/study/observationOrdersByDate.sql new file mode 100644 index 0000000..2318e32 --- /dev/null +++ b/nbri_ehr/resources/queries/study/observationOrdersByDate.sql @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT +s.*, +co.qcstate.label AS obsStatus +FROM + (SELECT + s1.*, + timestampadd('SQL_TSI_MINUTE', ((s1.hours * 60) + s1.minutes), s1.origDate) AS date, + ((s1.hours * 60) + s1.minutes) AS timeOffset + + FROM ( + SELECT + t1.lsid, + t1.dataset, + t1.id AS animalid, + coalesce(ft.hourofday, ((hour(t1.date) * 100) + minute(t1.date))) AS time, + (coalesce(ft.hourofday, (hour(t1.date) * 100)) / 100) AS hours, + + CASE WHEN ft.hourofday IS NOT NULL + THEN (((ft.hourofday / 100.0) - floor(ft.hourofday / 100)) * 100) + ELSE minute(t1.date) + END AS minutes, + + dr.date AS origDate, + + t1.frequency.meaning AS frequency, + t1.date AS startDate, + timestampdiff('SQL_TSI_DAY', cast(t1.dateOnly AS timestamp), dr.dateOnly) + 1 AS daysElapsed, + t1.enddate, + t1.category, + t1.area, + t1.performedby, + t1.remark, + t1.caseid.objectid AS caseid, + t1.taskid, + t1.type, + t1.objectid, + + t1.qcstate + FROM nbri_ehr.dateRange dr + JOIN + + -- order by category to replace string with Daily Obs + (SELECT * FROM study.observation_order ORDER BY category) t1 + ON (dr.dateOnly >= t1.dateOnly AND (dr.dateOnly <= t1.enddate OR t1.enddate IS NULL) AND + --technically the first day of the treatment is day 1, not day 0 + ((mod(CAST(timestampdiff('SQL_TSI_DAY', CAST(t1.dateOnly AS timestamp), dr.dateOnly) AS integer), t1.frequency.intervalindays) = 0 AND t1.frequency.intervalindays IS NOT NULL AND t1.frequency.dayofweek IS NULL)) + AND (t1.frequency.weekDays IS NULL OR LOCATE(CAST(dr.DayOfWeek AS VARCHAR), t1.frequency.weekDays) > 0) + ) + LEFT JOIN ehr_lookups.treatment_frequency_times ft ON ft.frequency = t1.frequency.meaning + WHERE t1.date IS NOT NULL + + ) s1 +) s +LEFT JOIN study.clinical_observations co ON co.scheduledDate IS NOT NULL AND s.date = co.scheduledDate AND co.orderId = s.objectid \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observationSchedule.query.xml b/nbri_ehr/resources/queries/study/observationSchedule.query.xml new file mode 100644 index 0000000..4d03aac --- /dev/null +++ b/nbri_ehr/resources/queries/study/observationSchedule.query.xml @@ -0,0 +1,20 @@ + + + + + + Observation Schedule + + + + Scheduled Date/Time + + + Observations + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observationSchedule.sql b/nbri_ehr/resources/queries/study/observationSchedule.sql new file mode 100644 index 0000000..5f6e0ec --- /dev/null +++ b/nbri_ehr/resources/queries/study/observationSchedule.sql @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + g.id, + g.scheduledDate, + COUNT(g.caseid) cases, + o.observations, + SUM(g.obsCount) AS obsCount, + o.orderIds, + o.status, + o.taskids, + MAX(g.type) AS type, + MAX(g.caseid) AS caseid +FROM +( + SELECT + sch.animalId as id, + sch.date AS scheduledDate, + sch.caseid, + sch.type, + COUNT(sch.category) AS obsCount + FROM observationOrdersByDate sch + GROUP BY + sch.animalId, + sch.date, + sch.caseid, + sch.type +) g +LEFT JOIN ( + SELECT + obs.animalId AS id, + obs.date AS scheduledDate, + GROUP_CONCAT(DISTINCT obs.category, ';') AS observations, + GROUP_CONCAT(obs.objectid, ';') AS orderIds, + GROUP_CONCAT(obs.obsStatus, ';') AS status, + GROUP_CONCAT(DISTINCT(obs.taskid), ';') AS taskids + FROM observationOrdersByDate obs + GROUP BY obs.animalId, obs.date +) o ON g.id = o.id AND g.scheduledDate = o.scheduledDate +GROUP BY + g.id, + g.scheduledDate, + o.observations, + o.orderIds, + o.status, + o.taskids diff --git a/nbri_ehr/resources/queries/study/observationSchedule/.qview.xml b/nbri_ehr/resources/queries/study/observationSchedule/.qview.xml new file mode 100644 index 0000000..b91d5d4 --- /dev/null +++ b/nbri_ehr/resources/queries/study/observationSchedule/.qview.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observation_order.js b/nbri_ehr/resources/queries/study/observation_order.js new file mode 100644 index 0000000..e9f0b13 --- /dev/null +++ b/nbri_ehr/resources/queries/study/observation_order.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observation_order.query.xml b/nbri_ehr/resources/queries/study/observation_order.query.xml new file mode 100644 index 0000000..ec28463 --- /dev/null +++ b/nbri_ehr/resources/queries/study/observation_order.query.xml @@ -0,0 +1,45 @@ + + + + + Observation Orders + + + + DateTime + + + false + DateTime + + + Category + + + Area + + ehr_lookups + observation_areas + value + + + + + Frequency + + ehr_lookups + treatment_frequency + meaning + + + + Ordered By + + + Type + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observation_order/.qview.xml b/nbri_ehr/resources/queries/study/observation_order/.qview.xml new file mode 100644 index 0000000..c02d2fb --- /dev/null +++ b/nbri_ehr/resources/queries/study/observation_order/.qview.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observation_order/Active Behavior Orders.qview.xml b/nbri_ehr/resources/queries/study/observation_order/Active Behavior Orders.qview.xml new file mode 100644 index 0000000..d4c5c11 --- /dev/null +++ b/nbri_ehr/resources/queries/study/observation_order/Active Behavior Orders.qview.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observation_order/Active Clinical Orders.qview.xml b/nbri_ehr/resources/queries/study/observation_order/Active Clinical Orders.qview.xml new file mode 100644 index 0000000..1638c87 --- /dev/null +++ b/nbri_ehr/resources/queries/study/observation_order/Active Clinical Orders.qview.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observation_order/Behavior Orders.qview.xml b/nbri_ehr/resources/queries/study/observation_order/Behavior Orders.qview.xml new file mode 100644 index 0000000..343d9b8 --- /dev/null +++ b/nbri_ehr/resources/queries/study/observation_order/Behavior Orders.qview.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/observation_order/Clinical Orders.qview.xml b/nbri_ehr/resources/queries/study/observation_order/Clinical Orders.qview.xml new file mode 100644 index 0000000..5e1e749 --- /dev/null +++ b/nbri_ehr/resources/queries/study/observation_order/Clinical Orders.qview.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/pairingSummary.query.xml b/nbri_ehr/resources/queries/study/pairingSummary.query.xml new file mode 100644 index 0000000..0d3b843 --- /dev/null +++ b/nbri_ehr/resources/queries/study/pairingSummary.query.xml @@ -0,0 +1,24 @@ + + + + + Pairing Summary + + + + 80 + + + Remark on Formation + + + Remark on Separation + + + Formation/Separation Type + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/pairingSummary.sql b/nbri_ehr/resources/queries/study/pairingSummary.sql new file mode 100644 index 0000000..e5befbe --- /dev/null +++ b/nbri_ehr/resources/queries/study/pairingSummary.sql @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + p.updatePairing, + p.Id, + (SELECT group_concat(distinct p2.Id, chr(10)) AS Ids FROM study.pairings p2 WHERE p.Id != p2.id AND p.pairId = p2.pairId) as otherIds, + p.pairid, + p.date, + p.enddate, + TIMESTAMPDIFF('SQL_TSI_DAY', p.date, coalesce(p.enddate,curdate())) as duration, + p.reason, + p.goal, + p.endState, + p.observation, + p.separationreason, + p.remark as formationRemark, + p.separationRemark, + p.performedby, + p.taskid, + p.type + +FROM study.pairings p \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/pairingSummary/.qview.xml b/nbri_ehr/resources/queries/study/pairingSummary/.qview.xml new file mode 100644 index 0000000..f0fdcf4 --- /dev/null +++ b/nbri_ehr/resources/queries/study/pairingSummary/.qview.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbri_ehr/resources/queries/study/pairingSummary/Active Pairing.qview.xml b/nbri_ehr/resources/queries/study/pairingSummary/Active Pairing.qview.xml new file mode 100644 index 0000000..14e0dfe --- /dev/null +++ b/nbri_ehr/resources/queries/study/pairingSummary/Active Pairing.qview.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbri_ehr/resources/queries/study/pairingSummary/Pairing History.qview.xml b/nbri_ehr/resources/queries/study/pairingSummary/Pairing History.qview.xml new file mode 100644 index 0000000..1a11617 --- /dev/null +++ b/nbri_ehr/resources/queries/study/pairingSummary/Pairing History.qview.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbri_ehr/resources/queries/study/pairings.js b/nbri_ehr/resources/queries/study/pairings.js new file mode 100644 index 0000000..7b55113 --- /dev/null +++ b/nbri_ehr/resources/queries/study/pairings.js @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_UPSERT, 'study', 'pairings', function(helper, scriptErrors, row, oldRow) { + + if (row.cage && row.Id && row.date && !triggerHelper.validateHousing(row.Id, row.cage, row.date)){ + EHR.Server.Utils.addError(scriptErrors, 'cage', 'Not housed in this location on this date', 'INFO'); + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/pairings.query.xml b/nbri_ehr/resources/queries/study/pairings.query.xml new file mode 100644 index 0000000..727a724 --- /dev/null +++ b/nbri_ehr/resources/queries/study/pairings.query.xml @@ -0,0 +1,90 @@ + + + + + + + + + + false + + + Pair Id + + + Location + + ehr_lookups + cage + location + cage + + + + Introduction Reason + 150 + + ehr_lookups + pairing_reason + value + + + + Goal + 100 + + ehr_lookups + pairing_goal + value + + + + Formation Type + + ehr_lookups + pairing_formation_types + value + + + + Remark on Formation + 200 + + + Interaction Summary + + ehr_lookups + pairing_observation + value + + + + End State + 100 + + ehr_lookups + pairing_goal + value + + + + Separation Reason + 100 + + ehr_lookups + pairing_separation_reason + value + + + + + Remark on Separation + 200 + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/pairings/.qview.xml b/nbri_ehr/resources/queries/study/pairings/.qview.xml new file mode 100644 index 0000000..26a8731 --- /dev/null +++ b/nbri_ehr/resources/queries/study/pairings/.qview.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbri_ehr/resources/queries/study/parentageSummary.query.xml b/nbri_ehr/resources/queries/study/parentageSummary.query.xml new file mode 100644 index 0000000..1efefbc --- /dev/null +++ b/nbri_ehr/resources/queries/study/parentageSummary.query.xml @@ -0,0 +1,25 @@ + + + + + Parentage Summary + + + Parent + + study + animal + id + + + + Relationship + + + Method + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/parentageSummary.sql b/nbri_ehr/resources/queries/study/parentageSummary.sql new file mode 100644 index 0000000..733a6ab --- /dev/null +++ b/nbri_ehr/resources/queries/study/parentageSummary.sql @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +SELECT + d.Id, + d.date, + d.dam as parent, + 'Dam' as relationship, + 'Observed' as method + +FROM study.demographics d +WHERE d.qcstate.publicdata = true + +UNION ALL + +SELECT + d.Id, + d.date, + d.sire as parent, + 'Sire' as relationship, + 'Observed' as method + +FROM study.demographics d +WHERE d.qcstate.publicdata = true diff --git a/nbri_ehr/resources/queries/study/physicalExam/.qview.xml b/nbri_ehr/resources/queries/study/physicalExam/.qview.xml new file mode 100644 index 0000000..caf3fb0 --- /dev/null +++ b/nbri_ehr/resources/queries/study/physicalExam/.qview.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prc.js b/nbri_ehr/resources/queries/study/prc.js new file mode 100644 index 0000000..1cca5b5 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prc.js @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +require("ehr/triggers").initScript(this); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_INSERT, 'study', 'prc', function(helper, scriptErrors, row, oldRow) { + if(row.orderid && triggerHelper.isProcedureOrderEntered(row.orderid)) { + EHR.Server.Utils.addError(scriptErrors, 'orderid', 'Procedure order has already been closed.', 'ERROR'); + } +}); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.COMPLETE, 'study', 'prc', function (event, errors, helper) { + + if (!helper.isValidateOnly()){ + var rows = helper.getRows(); + var orderIds = []; + for (var i=0;i + + + + + + + + Category + + ehr_lookups + data_category + value + + + + + Procedure + false + + ehr_lookups + procedures + rowid + name + + + + Order Id + + study + prc_order + objectid + + + + + ehr.context + /ehr/studyButtons.js + EHR.DatasetButtons.moreActionsHandler + + Grid Views + + + Charts + + + Export + + + Print + + + + + EHR.DatasetButtons.historyHandler(dataRegion, dataRegionName); + + + + + EHR.window.GetDistinctWindow.getDistinctHandler(dataRegionName); + + + + + EHR.DatasetButtons.showAuditHistoryHandler(dataRegionName); + + + + +
+
+
+ \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prc/.qview.xml b/nbri_ehr/resources/queries/study/prc/.qview.xml new file mode 100644 index 0000000..f5ed643 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prc/.qview.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prcOverdue.query.xml b/nbri_ehr/resources/queries/study/prcOverdue.query.xml new file mode 100644 index 0000000..2cf3260 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prcOverdue.query.xml @@ -0,0 +1,154 @@ + + + + + Overdue Procedures + objectid + + + true + + + true + + + + study + animal + Id + + + + 250 + + + 40 + + ehr_lookups + rooms + Room + + + + 40 + + + true + + core + qcstate + rowid + + + + false + true + Procedure Status + 150 + + + + + + FBEC5D + + + + + + FBEC5D + + + + + + FBEC5D + + + + + + FF0000 + + + + + + FBEC5D + + + + + + FBEC5D + + + + + + FF0000 + + + + + + FBEC5D + + + + + true + Task Id + + ehr + tasks + taskid + + /ehr/taskDetails.view?formtype=${taskid/formtype}&taskid=${taskid} + + + + ehr.context + /ehr/studyButtons.js + nbri_ehr/buttons/RecordProcedureButton.js + nbri_ehr/buttons/ProcedureOrderCompleteButton.js + EHR.DatasetButtons.moreActionsHandler + + Grid Views + + + Charts + + + Export + + + Print + + + + + NBRI_EHR.RecordProcedureButton.recordProceduresHandler(dataRegion); + + + + + NBRI_EHR.ProcedureOrderCompleteButton.procedureOrderCompleteHandler(dataRegion); + + + + + EHR.DatasetButtons.historyHandler(dataRegion, dataRegionName); + + + + + EHR.window.GetDistinctWindow.getDistinctHandler(dataRegionName); + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prcOverdue.sql b/nbri_ehr/resources/queries/study/prcOverdue.sql new file mode 100644 index 0000000..a7bbdfc --- /dev/null +++ b/nbri_ehr/resources/queries/study/prcOverdue.sql @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + po.procedureRecord, + po.Id, + po.procedure, + po.windowStart, + po.windowEnd, + timestampdiff('SQL_TSI_DAY', po.windowEnd, now()) as daysOverdue, + po.orderedby, + po.remark, + po.caseid, + po.objectid, + po.lsid, + CASE WHEN po.qcstate.label = 'Completed' THEN 'Completed' ELSE '' END as status +FROM prc_order po +WHERE now() > windowEnd AND po.qcstate.label != 'Completed' \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prcOverdue/.qview.xml b/nbri_ehr/resources/queries/study/prcOverdue/.qview.xml new file mode 100644 index 0000000..b8bf120 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prcOverdue/.qview.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prcOverdueNotification.sql b/nbri_ehr/resources/queries/study/prcOverdueNotification.sql new file mode 100644 index 0000000..dbb8de0 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prcOverdueNotification.sql @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + pod.Id, + pod.Id.demographics.species.common_name AS species, + pod.Id.curLocation.room.name AS room, + pod.Id.curLocation.cage.cage AS cage, + pod.procedure.name AS procedure, + pod.orderedby.displayName AS orderedBy, + pod.windowStart, + pod.windowEnd, + pod.daysOverdue, + pod.remark, +FROM prcOverdue pod +ORDER BY pod.daysOverdue DESC \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prcOverdueNotification/.qview.xml b/nbri_ehr/resources/queries/study/prcOverdueNotification/.qview.xml new file mode 100644 index 0000000..c647e7b --- /dev/null +++ b/nbri_ehr/resources/queries/study/prcOverdueNotification/.qview.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prcSchedule.query.xml b/nbri_ehr/resources/queries/study/prcSchedule.query.xml new file mode 100644 index 0000000..05c09db --- /dev/null +++ b/nbri_ehr/resources/queries/study/prcSchedule.query.xml @@ -0,0 +1,154 @@ + + + + + Procedure Schedule + objectid + + + true + + + true + + + + study + animal + Id + + + + 250 + + + 40 + + ehr_lookups + rooms + Room + + + + 40 + + + true + + core + qcstate + rowid + + + + false + true + Procedure Status + 150 + + + + + + FBEC5D + + + + + + FBEC5D + + + + + + FBEC5D + + + + + + FF0000 + + + + + + FBEC5D + + + + + + FBEC5D + + + + + + FF0000 + + + + + + FBEC5D + + + + + true + Task Id + + ehr + tasks + taskid + + /ehr/taskDetails.view?formtype=${taskid/formtype}&taskid=${taskid} + + + + ehr.context + /ehr/studyButtons.js + nbri_ehr/buttons/RecordProcedureButton.js + nbri_ehr/buttons/ProcedureOrderCompleteButton.js + EHR.DatasetButtons.moreActionsHandler + + Grid Views + + + Charts + + + Export + + + Print + + + + + NBRI_EHR.RecordProcedureButton.recordProceduresHandler(dataRegion); + + + + + NBRI_EHR.ProcedureOrderCompleteButton.procedureOrderCompleteHandler(dataRegion); + + + + + EHR.DatasetButtons.historyHandler(dataRegion, dataRegionName); + + + + + EHR.window.GetDistinctWindow.getDistinctHandler(dataRegionName); + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prcSchedule.sql b/nbri_ehr/resources/queries/study/prcSchedule.sql new file mode 100644 index 0000000..d8d80dc --- /dev/null +++ b/nbri_ehr/resources/queries/study/prcSchedule.sql @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +SELECT + po.procedureRecord, + po.Id, + po.procedure, + po.windowStart, + po.windowEnd, + po.orderedby, + po.remark, + po.caseid, + po.objectid, + po.lsid, + CASE WHEN po.qcstate.label = 'Completed' THEN 'Completed' ELSE '' END as status +FROM prc_order po +WHERE now() >= windowStart AND now() <= windowEnd \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prcSchedule/.qview.xml b/nbri_ehr/resources/queries/study/prcSchedule/.qview.xml new file mode 100644 index 0000000..4604b77 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prcSchedule/.qview.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prc_order.js b/nbri_ehr/resources/queries/study/prc_order.js new file mode 100644 index 0000000..1a87325 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prc_order.js @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +require("ehr/triggers").initScript(this); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_INSERT, 'study', 'prc_order', function (helper, scriptErrors, row, oldRow) { + if (!helper.isValidateOnly()) { + row.qcstate = helper.getJavaHelper().getQCStateForLabel('Request: Approved').getRowId(); + row.qcstateLabel = 'Request: Approved'; + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prc_order.query.xml b/nbri_ehr/resources/queries/study/prc_order.query.xml new file mode 100644 index 0000000..ef4dba7 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prc_order.query.xml @@ -0,0 +1,84 @@ + + + + + Procedure Orders + + + + + + + + + Window Start + false + + + Window End + false + + + Category + + ehr_lookups + data_category + value + + + + + Procedure + false + + ehr_lookups + procedures + rowid + name + + + + + ehr.context + /ehr/studyButtons.js + nbri_ehr/buttons/ProcedureOrderCompleteButton.js + EHR.DatasetButtons.moreActionsHandler + + Grid Views + + + Charts + + + Export + + + Print + + + + + NBRI_EHR.ProcedureOrderCompleteButton.procedureOrderCompleteHandler(dataRegion); + + + + + EHR.DatasetButtons.historyHandler(dataRegion, dataRegionName); + + + + + EHR.window.GetDistinctWindow.getDistinctHandler(dataRegionName); + + + + + EHR.DatasetButtons.showAuditHistoryHandler(dataRegionName); + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prc_order/.qview.xml b/nbri_ehr/resources/queries/study/prc_order/.qview.xml new file mode 100644 index 0000000..b9de6c1 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prc_order/.qview.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prc_order_report.query.xml b/nbri_ehr/resources/queries/study/prc_order_report.query.xml new file mode 100644 index 0000000..ad316a0 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prc_order_report.query.xml @@ -0,0 +1,84 @@ + + + + + Procedure Order Report + + + + + + + + + Window Start + false + + + Window End + false + + + Category + + ehr_lookups + data_category + value + + + + + Procedure + false + + ehr_lookups + procedures + rowid + name + + + + + ehr.context + /ehr/studyButtons.js + nbri_ehr/buttons/ProcedureOrderCompleteButton.js + EHR.DatasetButtons.moreActionsHandler + + Grid Views + + + Charts + + + Export + + + Print + + + + + NBRI_EHR.ProcedureOrderCompleteButton.procedureOrderCompleteHandler(dataRegion); + + + + + EHR.DatasetButtons.historyHandler(dataRegion, dataRegionName); + + + + + EHR.window.GetDistinctWindow.getDistinctHandler(dataRegionName); + + + + + EHR.DatasetButtons.showAuditHistoryHandler(dataRegionName); + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prc_order_report.sql b/nbri_ehr/resources/queries/study/prc_order_report.sql new file mode 100644 index 0000000..847bedd --- /dev/null +++ b/nbri_ehr/resources/queries/study/prc_order_report.sql @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT *, CASE WHEN qcstate.label = 'Completed' THEN 'Completed' ELSE '' END as status FROM study.prc_order \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/prc_order_report/.qview.xml b/nbri_ehr/resources/queries/study/prc_order_report/.qview.xml new file mode 100644 index 0000000..62d20f0 --- /dev/null +++ b/nbri_ehr/resources/queries/study/prc_order_report/.qview.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/pregnancy.js b/nbri_ehr/resources/queries/study/pregnancy.js new file mode 100644 index 0000000..16e8968 --- /dev/null +++ b/nbri_ehr/resources/queries/study/pregnancy.js @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); + +var triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.ON_BECOME_PUBLIC, 'study', 'pregnancy', function(scriptErrors, helper, row, oldRow) { + if (!helper.isETL()) { + + var outcomeRec = { + Id: row.Id, + date: row.date, + result: row.result + } + triggerHelper.sendPregnancyOutcomeNotification(row.Id, outcomeRec); + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/pregnancy.query.xml b/nbri_ehr/resources/queries/study/pregnancy.query.xml new file mode 100644 index 0000000..35663f8 --- /dev/null +++ b/nbri_ehr/resources/queries/study/pregnancy.query.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + Delivery Date + + + Outcome + + ehr_lookups + pregnancy_result + value + title + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/protocolAssignment.js b/nbri_ehr/resources/queries/study/protocolAssignment.js new file mode 100644 index 0000000..cf6fde2 --- /dev/null +++ b/nbri_ehr/resources/queries/study/protocolAssignment.js @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); +var protocolData = {}; +var prevAnimalId; +var prevDate; + +var missing = []; + +var count = 0; + +function getLastAssignment(id){ + var batchLastDate; + + LABKEY.Query.selectRows({ + schemaName: 'study', + queryName: 'protocolAssignment', + columns: 'Id,date', + filterArray: [LABKEY.Filter.create('Id', id)], + sort: '-date', + success: function (results) { + if (results.rows.length) { + batchLastDate = results.rows[0].date; + } + }, + scope: this + }); + + return batchLastDate; +} + +function onInit(event, helper){ + + if (helper.isETL()) { + LABKEY.Query.selectRows({ + schemaName: 'ehr', + queryName: 'protocol', + columns: 'title,objectid', + success: function (results) { + if (results.rows.length) { + for (var i = 0; i < results.rows.length; i++) { + let rec = results.rows[i]; + protocolData[rec.objectid] = rec.title; + } + } + }, + scope: this + }); + } +} + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_INSERT, 'study', 'protocolAssignment', function (helper, scriptErrors, row, oldRow) { + + if (helper.isETL()) { + var isTransfer = prevAnimalId === row.Id; + + if (row.remark) { + var remarkTextArr = row.remark.split(':'); + var toProtocol = remarkTextArr[3].split(' (')[0]; // Get "To Protocol:" value without segment + var protocolId; + + protocolId = getProtocolIdByName(toProtocol); + if (!protocolId || protocolId === 'undefined') { + if (missing.indexOf(toProtocol) === -1) + missing.push(toProtocol) + } + else { + row.protocol = protocolId; + } + if (isTransfer) { + if (row.enddate) { + // End date will initially have animal death/departure. Override if the transfer is older. + var death = new Date(row.enddate); + var prev = new Date(prevDate); + + // Sanity check + if (prev < death) { + row.enddate = prevDate; + } + } + else { + row.enddate = prevDate; + } + } + else if (count === 0) { + // This handles batch boundary row for full truncate ETL, which is the only ETL setup for this currently. + // Gets previous date from db for first row in batch + var batchLastDate = getLastAssignment(row.Id); + if (batchLastDate) { + row.enddate = batchLastDate; + } + } + + if (row.enddate === 'undefined') { + console.log("end date not found for animal event - " + row.animalEventId); + } + } + + prevAnimalId = row.Id; + prevDate = row.date; + count++; + } + +}); + + +function getProtocolIdByName(protocolName) { + var protocols = Object.keys(protocolData); + + // Search protocols for exact case-insensitive match + for (var i = 0; i< protocols.length; i++) { + var pName = protocolData[protocols[i]] ; + if (pName && protocolName.trim().toLowerCase() === pName.toString().toLowerCase()) { + return protocols[i]; + } + } + + // If exact match not found, search for partial match at beginning of protocol + for (i = 0; i< protocols.length; i++) { + pName = protocolData[protocols[i]] ; + if (pName && protocolName.trim().toLowerCase().indexOf(pName.toString().toLowerCase()) === 0) { + return protocols[i]; + } + } +} diff --git a/nbri_ehr/resources/queries/study/protocolAssignment.query.xml b/nbri_ehr/resources/queries/study/protocolAssignment.query.xml new file mode 100644 index 0000000..ac61d1c --- /dev/null +++ b/nbri_ehr/resources/queries/study/protocolAssignment.query.xml @@ -0,0 +1,30 @@ + + + + + + + + + + true + + + Protocol + + ehr + protocol + protocol + title + + + + + + true + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/protocolAssignment/Active Assignments.qview.xml b/nbri_ehr/resources/queries/study/protocolAssignment/Active Assignments.qview.xml new file mode 100644 index 0000000..1f07c5a --- /dev/null +++ b/nbri_ehr/resources/queries/study/protocolAssignment/Active Assignments.qview.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/recentCases.sql b/nbri_ehr/resources/queries/study/recentCases.sql new file mode 100644 index 0000000..b392a23 --- /dev/null +++ b/nbri_ehr/resources/queries/study/recentCases.sql @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +PARAMETERS(SubjectId VARCHAR, CaseCategory VARCHAR) + +SELECT * FROM study.cases +WHERE Id = SubjectId AND category = CaseCategory +ORDER BY date DESC LIMIT 20 \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/serology.query.xml b/nbri_ehr/resources/queries/study/serology.query.xml new file mode 100644 index 0000000..99f97bd --- /dev/null +++ b/nbri_ehr/resources/queries/study/serology.query.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + Date + + + Lab + + + Type + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/serology/.qview.xml b/nbri_ehr/resources/queries/study/serology/.qview.xml new file mode 100644 index 0000000..2effb18 --- /dev/null +++ b/nbri_ehr/resources/queries/study/serology/.qview.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/tissueDisposition.js b/nbri_ehr/resources/queries/study/tissueDisposition.js new file mode 100644 index 0000000..e9f0b13 --- /dev/null +++ b/nbri_ehr/resources/queries/study/tissueDisposition.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/tissueDisposition.query.xml b/nbri_ehr/resources/queries/study/tissueDisposition.query.xml new file mode 100644 index 0000000..494a4ab --- /dev/null +++ b/nbri_ehr/resources/queries/study/tissueDisposition.query.xml @@ -0,0 +1,40 @@ + + + + + + + Tissue + 80 + + ehr_lookups + necropsy_tissue + value + + + + Tissue Disposition Code + 180 + + ehr_lookups + necropsy_disposition_codes + value + + + + true + + + true + + + true + + + true + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/tissueDisposition/.qview.xml b/nbri_ehr/resources/queries/study/tissueDisposition/.qview.xml new file mode 100644 index 0000000..428b937 --- /dev/null +++ b/nbri_ehr/resources/queries/study/tissueDisposition/.qview.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/treatmentSchedule.query.xml b/nbri_ehr/resources/queries/study/treatmentSchedule.query.xml new file mode 100644 index 0000000..59d1f2e --- /dev/null +++ b/nbri_ehr/resources/queries/study/treatmentSchedule.query.xml @@ -0,0 +1,187 @@ + + + + + Treatment Schedule + /EHR/treatmentDetails.view?key=${lsid} + primaryKey + + + true + + + true + true + + + true + + + + study + animal + Id + + + + Treatment Start Date + DateTime + + + false + Treatment + + ehr_lookups + snomed + code + + + + + true + + ehr_lookups + treatment_frequency + meaning + + + + 250 + + + 40 + + ehr_lookups + rooms + Room + + + + 40 + + + true + + + true + + core + qcstate + rowid + + + + Concentration + + + Amount + + + Volume + + + false + true + Treatment Status + 150 + + + + + + FBEC5D + + + + + + FBEC5D + + + + + + FBEC5D + + + + + + FF0000 + + + + + + FBEC5D + + + + + + FBEC5D + + + + + + FF0000 + + + + + + FBEC5D + + + + + false + Task Id + + ehr + tasks + taskid + + /ehr/taskDetails.view?formtype=${taskid/formtype}&taskid=${taskid} + + + + ehr.context + /ehr/studyButtons.js + nbri_ehr/buttons/RecordTreatmentButton.js + EHR.DatasetButtons.moreActionsHandler + + Grid Views + + + Charts + + + Export + + + Print + + + + + NBRI_EHR.RecordTreatmentButton.recordTreatmentsHandler(dataRegion); + + + + + EHR.DatasetButtons.historyHandler(dataRegion, dataRegionName); + + + + + EHR.window.GetDistinctWindow.getDistinctHandler(dataRegionName); + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/treatmentSchedule.sql b/nbri_ehr/resources/queries/study/treatmentSchedule.sql new file mode 100644 index 0000000..068cb4e --- /dev/null +++ b/nbri_ehr/resources/queries/study/treatmentSchedule.sql @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +SELECT +d.id, +d_alias.alias AS Name, +d.calculated_status, +s.*, +s.objectid AS treatmentid, +drug.treatmentStatus, +s.objectid || '-pkSeparator-' || s.date AS primaryKey -- -pkSeparator- is used to separate the two parts of the primary key in RecordTreatmentButton.js +FROM study.demographics d +JOIN( + SELECT + s1.*, + timestampadd('SQL_TSI_MINUTE', ((s1.hours * 60) + s1.minutes), s1.origDate) AS date, + ((s1.hours * 60) + s1.minutes) AS timeOffset + FROM ( + SELECT + t1.lsid, + t1.objectid, + t1.dataset, + t1.id AS animalid, + + COALESCE(ft.hourofday, ((hour(t1.date) * 100) + minute(t1.date))) AS time, + (COALESCE(ft.hourofday, (hour(t1.date) * 100)) / 100) AS hours, + CASE + WHEN (ft.hourofday IS NOT NULL) THEN (((ft.hourofday / 100.0) - floor(ft.hourofday / 100)) * 100) + ELSE minute(t1.date) + END AS minutes, + dr.date AS origDate, + t1.category, + t1.frequency.meaning AS frequency, + t1.date AS startDate, + timestampdiff('SQL_TSI_DAY', cast(t1.dateOnly AS timestamp), dr.dateOnly) + 1 AS daysElapsed, + t1.enddate, + t1.code, + t1.treatmentRecord, + t1.volume, + t1.vol_units, + t1.concentration, + t1.conc_units, + t1.amount, + t1.amount_units, + t1.amountWithUnits, + t1.amountAndVolume, + t1.dosage, + t1.dosage_units, + t1.route, + IFDEFINED(t1.reason) AS reason, + t1.performedby, + t1.remark, + t1.caseid, + t1.orderedby, + t1.qcstate + FROM nbri_ehr.dateRange dr + JOIN study."Treatment Orders" t1 ON (dr.dateOnly >= t1.dateOnly AND + --technically the first day of the treatment is day 1, not day 0 + ((mod(CAST(timestampdiff('SQL_TSI_DAY', CAST(t1.dateOnly AS timestamp), dr.dateOnly) AS integer), t1.frequency.intervalindays) = 0 AND t1.frequency.intervalindays IS NOT NULL AND t1.frequency.dayofweek IS NULL )) + AND (t1.frequency.weekDays IS NULL OR LOCATE(CAST(dr.DayOfWeek AS VARCHAR), t1.frequency.weekDays) > 0) + ) + LEFT JOIN ehr_lookups.treatment_frequency_times ft ON ft.frequency = t1.frequency.meaning + --NOTE: if we run this report on a future interval, we want to include those treatments + WHERE t1.date IS NOT NULL + + ) s1 + +) s ON (s.animalid = d.id) +LEFT JOIN ( + SELECT treatmentid, IFDEFINED(scheduledDate) AS scheduledDate, MAX(qcstate.label) AS treatmentStatus + FROM study.drug + GROUP BY treatmentid, IFDEFINED(scheduledDate) +) drug ON s.objectid = drug.treatmentid AND s.date = drug.scheduledDate +LEFT JOIN (SELECT Id, GROUP_CONCAT(alias, ', ') alias FROM alias WHERE category.title = 'Name' GROUP BY Id) d_alias ON d.id = d_alias.id +WHERE (d.lastDayatCenter IS NULL OR d.lastDayAtCenter > s.enddate OR s.enddate IS NULL) + AND s.date >= s.startDate AND (s.enddate IS NULL OR s.date <= s.enddate) \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/treatmentSchedule/.qview.xml b/nbri_ehr/resources/queries/study/treatmentSchedule/.qview.xml new file mode 100644 index 0000000..4c57f0b --- /dev/null +++ b/nbri_ehr/resources/queries/study/treatmentSchedule/.qview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/treatmentSchedule/Clinical Medications.qview.xml b/nbri_ehr/resources/queries/study/treatmentSchedule/Clinical Medications.qview.xml new file mode 100644 index 0000000..5698039 --- /dev/null +++ b/nbri_ehr/resources/queries/study/treatmentSchedule/Clinical Medications.qview.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/treatment_order.js b/nbri_ehr/resources/queries/study/treatment_order.js new file mode 100644 index 0000000..4589b9c --- /dev/null +++ b/nbri_ehr/resources/queries/study/treatment_order.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +require("ehr/triggers").initScript(this); + +let triggerHelper = new org.labkey.nbri_ehr.query.NBRI_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_UPSERT, 'study', 'treatment_order', function(helper, scriptErrors, row, oldRow) { + // Max reasonable amount warning. Error when the amount is greater than the max reasonable amount + if (row.code) { + let drugFormulary = triggerHelper.getFormularyForDrug(row.code); + if (drugFormulary && drugFormulary.maxAmount && row.amount > drugFormulary.maxAmount) { + EHR.Server.Utils.addError(scriptErrors, 'amount', 'Amount is greater than the maximum reasonable amount: ' + drugFormulary.maxAmount, 'ERROR'); + } + } + + if (row.volume && !row.vol_units) { + EHR.Server.Utils.addError(scriptErrors, 'volume', 'Units required for volume.', 'ERROR'); + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/treatment_order.query.xml b/nbri_ehr/resources/queries/study/treatment_order.query.xml new file mode 100644 index 0000000..c2849aa --- /dev/null +++ b/nbri_ehr/resources/queries/study/treatment_order.query.xml @@ -0,0 +1,170 @@ + + + + + /EHR/treatmentDetails.view?key=${lsid} + + + + + + + + + Begin Date + + + End Date + false + + + + ehr + project + project + + + + Category + + ehr_lookups + data_category + value + + + Depending on what is selected, the treatment will appear on a different schedule (ie. Clinical, Surgical, etc) + + + false + Treatment + + ehr_lookups + snomed + code + + + + Frequency + + ehr_lookups + treatment_frequency + meaning + + + + + + + + + Route + + ehr_lookups + routes + route + + + 40 + + + Volume + + + Volume Units + + ehr_lookups + volume_units + unit + + + + + Amount + + + Amount Units + + ehr_lookups + amount_units + unit + + + + + Drug Conc + + + Conc Units + + ehr_lookups + conc_units + unit + + + + + Dosage + + + Dosage Units + + ehr_lookups + dosage_units + unit + + + + + true + + + false + + + Parent ID + + + + ehr.context + /ehr/studyButtons.js + /nbri_ehr/window/MarkTreatmentCompletedWindow.js + EHR.DatasetButtons.moreActionsHandler + + Grid Views + + + Charts + + + Export + + + Print + + + + + EHR.DatasetButtons.historyHandler(dataRegion, dataRegionName); + + + + + EHR.window.GetDistinctWindow.getDistinctHandler(dataRegionName); + + + + + EHR.DatasetButtons.showAuditHistoryHandler(dataRegionName); + + + + + NBRI_EHR.window.MarkTreatmentCompletedWindow.buttonHandler(dataRegionName, 'study', 'treatment_order', 'datefield', 'lsid'); + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/treatment_order/.qview.xml b/nbri_ehr/resources/queries/study/treatment_order/.qview.xml new file mode 100644 index 0000000..27608af --- /dev/null +++ b/nbri_ehr/resources/queries/study/treatment_order/.qview.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/treatment_order/Behavior Active Treatment Orders.qview.xml b/nbri_ehr/resources/queries/study/treatment_order/Behavior Active Treatment Orders.qview.xml new file mode 100644 index 0000000..a495f9e --- /dev/null +++ b/nbri_ehr/resources/queries/study/treatment_order/Behavior Active Treatment Orders.qview.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/treatment_order/Clinical Active Treatment Orders.qview.xml b/nbri_ehr/resources/queries/study/treatment_order/Clinical Active Treatment Orders.qview.xml new file mode 100644 index 0000000..6fc59ae --- /dev/null +++ b/nbri_ehr/resources/queries/study/treatment_order/Clinical Active Treatment Orders.qview.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/vitals.js b/nbri_ehr/resources/queries/study/vitals.js new file mode 100644 index 0000000..334a25c --- /dev/null +++ b/nbri_ehr/resources/queries/study/vitals.js @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/vitals.query.xml b/nbri_ehr/resources/queries/study/vitals.query.xml new file mode 100644 index 0000000..29e22d9 --- /dev/null +++ b/nbri_ehr/resources/queries/study/vitals.query.xml @@ -0,0 +1,33 @@ + + + + + + + + + Category + + ehr_lookups + data_category + value + + + + + + + + + + EKG + + + Pulse Oximetry + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/vitals/.qview.xml b/nbri_ehr/resources/queries/study/vitals/.qview.xml new file mode 100644 index 0000000..f3b831c --- /dev/null +++ b/nbri_ehr/resources/queries/study/vitals/.qview.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/weight.query.xml b/nbri_ehr/resources/queries/study/weight.query.xml new file mode 100644 index 0000000..d9ee743 --- /dev/null +++ b/nbri_ehr/resources/queries/study/weight.query.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + Weight (kg) + 0.### + true + + + true + + + Category + true + + ehr_lookups + data_category + value + + + + + +
+
+
+
\ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/weight/.qview.xml b/nbri_ehr/resources/queries/study/weight/.qview.xml new file mode 100644 index 0000000..b27ffe4 --- /dev/null +++ b/nbri_ehr/resources/queries/study/weight/.qview.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/referenceStudy/.labkey/protocols/kinship/default.xml b/nbri_ehr/resources/referenceStudy/.labkey/protocols/kinship/default.xml new file mode 100644 index 0000000..b1fede0 --- /dev/null +++ b/nbri_ehr/resources/referenceStudy/.labkey/protocols/kinship/default.xml @@ -0,0 +1,3 @@ + + + true \ No newline at end of file diff --git a/nbri_ehr/resources/referenceStudy/folder.xml b/nbri_ehr/resources/referenceStudy/folder.xml new file mode 100644 index 0000000..0abf4b0 --- /dev/null +++ b/nbri_ehr/resources/referenceStudy/folder.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/referenceStudy/study/datasets/PrimateElectronicHealthRecord.dataset b/nbri_ehr/resources/referenceStudy/study/datasets/PrimateElectronicHealthRecord.dataset new file mode 100644 index 0000000..9a762dd --- /dev/null +++ b/nbri_ehr/resources/referenceStudy/study/datasets/PrimateElectronicHealthRecord.dataset @@ -0,0 +1,19 @@ +# default group can be used to avoid repeating definitions for each dataset +# +# action=[REPLACE,APPEND,DELETE] (default:REPLACE) +# deleteAfterImport=[TRUE|FALSE] (default:FALSE) + +default.action=REPLACE +default.deleteAfterImport=FALSE + +# map a source tsv column (right side) to a property name or full propertyURI (left) +# predefined properties: ParticipantId, SiteId, VisitId, Created +default.property.ParticipantId=ptid +default.property.Created=dfcreate + +# use to map from filename->datasetid +# NOTE: if there are NO explicit import definitions, we will try to import all files matching pattern +# NOTE: if there are ANY explicit mapping, we will only import listed datasets + +default.filePattern=dataset(\\d*).tsv +default.importAllMatches=FALSE \ No newline at end of file diff --git a/nbri_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml b/nbri_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml new file mode 100644 index 0000000..1d03f01 --- /dev/null +++ b/nbri_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml b/nbri_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml new file mode 100644 index 0000000..f8d49b0 --- /dev/null +++ b/nbri_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml @@ -0,0 +1,1514 @@ + + + + + + varchar + urn:ehr.labkey.org/#TaskId + + + varchar + urn:ehr.labkey.org/#ParentId + + + Performed By + varchar + urn:ehr.labkey.org/#PerformedBy + + + varchar + urn:ehr.labkey.org/#Description + + + varchar + urn:ehr.labkey.org/#Remark + + + entityid + urn:ehr.labkey.org/#ObjectId + true + + + + + Alias + Records alternative identifiers and aliases assigned to individual primates within the facility. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + + varchar + + +
+ + Arrival + Tracks the arrival of primates into the research facility, including source, acquisition type, and associated documentation. + + + entityid + urn:ehr.labkey.org/#ObjectId + false + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + Location + varchar + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Source Facility + varchar + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + + varchar + + + integer + urn:ehr.labkey.org/#Project + + + varchar + + + varchar + + + varchar + + + boolean + + +
+ + Project Assignments + Records project assignments for individual primates, linking animals to specific research projects with start and end dates. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + + + integer + urn:ehr.labkey.org/#Project + + +
+ + Biopsy + Documents biopsy procedures performed on primates, including tissue type and associated pathology reports. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Type + varchar + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + +
+ + Protocol Assignments + Tracks the assignment of primates to IACUC-approved research protocols with effective date ranges. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + + + varchar + + +
+ + Birth + Records birth events for primates born within the facility, including location and associated protocols. + + + entityid + urn:ehr.labkey.org/#ObjectId + false + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + varchar + Location + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + integer + urn:ehr.labkey.org/#Project + + + varchar + + +
+ + Blood Draws + Tracks blood draw procedures performed on primates, including volume, sample type, tube type, and purpose. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Type + varchar + + + double + + + varchar + urn:ehr.labkey.org/#CaseId + + + varchar + + + varchar + + + double + + + varchar + + + integer + + + varchar + + +
+ + Breeder + Records breeding evaluations and reproductive assessments for primates in the colony breeding program. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Type + varchar + + + Result + varchar + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + +
+ + Clinical/Behavior Observations + Documents clinical and behavioral observations recorded during routine monitoring and veterinary assessments of primates. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + + + Type + varchar + + + varchar + + + varchar + + + varchar + urn:ehr.labkey.org/#CaseId + + + varchar + + + varchar + + +
+ + Clinical Remarks + Stores veterinary clinical remarks and SOAP notes associated with primate health assessments and case management. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + + varchar + + + varchar + + + varchar + + + varchar + + + varchar + + + timestamp + + + timestamp + + + timestamp + + + varchar + urn:ehr.labkey.org/#CaseId + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + +
+ + Demographics + Contains core demographic information for each primate, including species, sex, parentage, birth and death dates, and colony status. + + + entityid + urn:ehr.labkey.org/#ObjectId + false + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + sex + + + varchar + + + varchar + + + timestamp + + + timestamp + + + varchar + + + timestamp + + + varchar + + + varchar + + + varchar + + + varchar + + + varchar + + + varchar + + + integer + + + varchar + + + varchar + + + varchar + + +
+ + Departure + Records the departure of primates from the research facility, including destination information. + + + entityid + urn:ehr.labkey.org/#ObjectId + false + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + +
+ + Deaths + Documents primate deaths, including date, cause of death, and terminal body weight. + + + entityid + urn:ehr.labkey.org/#ObjectId + false + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + double + + +
+ + Exemptions + Tracks approved exemptions from standard care or procedural requirements for individual primates. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + urn:ehr.labkey.org/#EndDate + + + varchar + + + varchar + + +
+ + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + timestamp + urn:ehr.labkey.org/#EndDate + + + Animal Record Flags + Stores active record flags and status indicators applied to individual primates for colony management purposes. +
+ + Histopathology + Records histopathology findings from tissue examinations performed on primates, including diagnoses and associated reports. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + + varchar + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + +
+ + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + + Historical Other + Captures miscellaneous historical health and research records for primates that do not fit other specific categories. +
+ + Housing + Tracks housing assignments and location transfers for primates within the research facility. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Location + varchar + + + varchar + + + varchar + + + timestamp + + + varchar + urn:ehr.labkey.org/#CaseId + + + + + cage + + +
+ + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + double + + + timestamp + urn:ehr.labkey.org/#EndDate + + + Inbreeding Coefficients + Records calculated inbreeding coefficients for primates to support genetic management of the colony. +
+ + Necropsy + Documents necropsy (postmortem) examination findings for primates, including gross and histological observations, diagnoses, and reports. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Category + varchar + + + Accession Number + varchar + + + Condition of Specimen + varchar + + + Physical Condition + varchar + + + Relevant History + varchar + + + Gross Abnormalities + varchar + + + Diagnosis + varchar + + + Name/State/License no. (quarantine only) + varchar + + + varchar + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + +
+ + Gross Pathology + Records gross pathology findings observed during necropsy examinations of primates. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + Date of Exam + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + +
+ + Tissue Disposition + Tracks the disposition of tissue samples collected during necropsy of primates. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + +
+ + Pairings + Records social pairing and group housing arrangements for primates, including formation type, compatibility observations, and separation details. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + urn:ehr.labkey.org/#EndDate + + + varchar + + + varchar + + + Location + varchar + + + varchar + + + varchar + + + varchar + + + varchar + + + varchar + + + varchar + + + varchar + + +
+ + Physical Exam + Documents physical examination findings and measurements recorded during veterinary assessments of primates. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + double + + + Units + integer + + + varchar + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + +
+ + Procedures + Records research and veterinary procedures performed on primates, including procedure type, category, and associated case information. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + + varchar + urn:ehr.labkey.org/#CaseId + + + varchar + + + integer + + + Ordered By + varchar + + + varchar + + +
+ + Procedure Orders + Tracks scheduled procedure orders for primates, including ordering veterinarian and scheduling windows. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + integer + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Window Start + timestamp + + + Window End + timestamp + + + varchar + urn:ehr.labkey.org/#CaseId + + + varchar + + + Ordered By + varchar + + +
+ + Serology + Records serological test results for primates, used for infectious disease screening and colony health monitoring. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + +
+ + Problem List + Maintains the active and historical problem list for individual primates, supporting ongoing veterinary case management. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + + timestamp + + +
+ + Drug Administration + Records drug and medication administrations for primates, including dosage, route, concentration, and ordering clinician. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Type + varchar + + + Amount + double + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + + varchar + + + varchar + + + double + + + varchar + + + varchar + + + double + + + varchar + + + double + + + varchar + + + varchar + + + varchar + urn:ehr.labkey.org/#CaseId + + + timestamp + + + varchar + + + Ordered By + varchar + + +
+ + Treatment Cases + Tracks veterinary treatment cases for primates, supporting clinical case management from opening through resolution. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + urn:ehr.labkey.org/#EndDate + + + varchar + + + Case category + varchar + + + Open Remark + varchar + + + Close Remark + varchar + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + + varchar + + + varchar + + + varchar + + + varchar + urn:ehr.labkey.org/#VetReview + + + timestamp + urn:ehr.labkey.org/#VetReviewDate + + + varchar + urn:ehr.labkey.org/#CaseId + + + varchar + + +
+ + Treatment Orders + Stores standing treatment orders for primates, including medication details, dosing frequency, and prescribing veterinarian. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + timestamp + + + varchar + + + varchar + + + double + + + varchar + + + varchar + + + double + + + varchar + + + double + + + varchar + + + varchar + + + varchar + + + varchar + urn:ehr.labkey.org/#CaseId + + + Ordered By + varchar + + + End Treatment Ordered By + varchar + + +
+ + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Blood Pressure + varchar + + + Temperature + double + + + Heart Rate + double + + + Respiration Rate + double + + + Pulse Rate + double + + + double + + + double + + + Type + varchar + + + Units + integer + + + varchar + urn:ehr.labkey.org/#CaseId + + + varchar + + + Vital Signs + Records vital sign measurements for primates, including temperature, heart rate, respiration rate, blood pressure, and pulse oximetry. +
+ + Weight + Tracks body weight measurements for primates, used for health monitoring and drug dosage calculations. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + double + + + Units + integer + + + varchar + urn:ehr.labkey.org/#CaseId + + + varchar + + +
+ + Pregnancy Outcomes + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + Type + varchar + + + Result + varchar + + + Diagnosis + varchar + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + +
+ + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + + + varchar + + + Attachment File + varchar + http://cpas.fhcrc.org/exp/xml#fileLink + + + Notes +
+ + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + Result + double + + + Chemistry Results +
+ + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + Fostering +
+ + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + + varchar + urn:ehr.labkey.org/#CaseId + + + timestamp + urn:ehr.labkey.org/#EndDate + + + integer + + + varchar + + + varchar + + + Observation Orders +
+ + Animal Training + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + urn:ehr.labkey.org/#EndDate + + + varchar + + + varchar + + + varchar + + + varchar + + +
+
\ No newline at end of file diff --git a/nbri_ehr/resources/referenceStudy/study/study.xml b/nbri_ehr/resources/referenceStudy/study/study.xml new file mode 100644 index 0000000..7f13240 --- /dev/null +++ b/nbri_ehr/resources/referenceStudy/study/study.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/reports/additionalReports.tsv b/nbri_ehr/resources/reports/additionalReports.tsv new file mode 100644 index 0000000..98acfbe --- /dev/null +++ b/nbri_ehr/resources/reports/additionalReports.tsv @@ -0,0 +1,52 @@ +reportname category reporttype reporttitle visible containerpath schemaname queryname viewname report datefieldname todayonly queryhaslocation sort_order QCStateLabelFieldName description +MHC Genetics query MHC TRUE study MHC FALSE FALSE qcstate/publicdata This report shows MHC type +assignment Colony Management query Protocol Assignment TRUE study protocolAssignment FALSE FALSE qcstate/publicdata This report shows protocol assignments +grossPathology Pathology query Gross Pathology TRUE study grossPathology FALSE FALSE qcstate/publicdata This is for histopathology reports +tissueDisposition Pathology query Tissue Disposition TRUE study tissueDisposition FALSE FALSE qcstate/publicdata This is for histopathology reports +histopathology Pathology query Histopathology TRUE study histopathology FALSE FALSE qcstate/publicdata This is for histopathology reports +clinical_observations Clinical query Clinical Observations TRUE study clinical_observationsSummary Clinical date FALSE FALSE qcstate/publicdata This report displays clinical observations for the selected animal +foster Reproductive Management query Fostering TRUE study foster FALSE FALSE qcstate/publicdata This is for animal fostering data +projects Colony Management query Project Assignment TRUE study assignment FALSE FALSE qcstate/publicdata This is for project assignments +chemistry Clinical query Chemistry TRUE study chemistryResults FALSE FALSE qcstate/publicdata This is for chemistry results +alias Colony Management query Aliases true study demographicsAliases false false qcstate/publicdata This report shows the animal aliases +notes Colony Management query Notes true study notes false false qcstate/publicdata This report shows the animal notes +activeClinTreatmentOrders Clinical query Active Clinical Medication Orders true study treatment_order Clinical Active Treatment Orders date false false qcstate/publicdata This report contains the treatment orders entered for each animal +activeBehaviorTreatmentOrders Behavior query Active Behavior Medication Orders true study treatment_order Behavior Active Treatment Orders date false false qcstate/publicdata This report contains the treatment orders entered for each animal +allTreatments Clinical query All Treatment Orders true study treatment_order false false qcstate/publicdata This report shows all treatment orders +behTreatments Behavior query All Behavior Medication Orders true study treatment_order behavior false false qcstate/publicdata This report shows all behavior treatment orders +behDrug Behavior query Behavior Drug Administration true study drug Behavior false false qcstate/publicdata This report shows all behavior drug administrations +FileRepository General js File Repository true study FileRepository false false qcstate/publicdata File Repository for uploading and viewing animal related files +observationSchedule Daily Reports js Today's Observation Schedule true study observationSchedule date false false qcstate/publicdata This report contains a list of today's treatments to be administered +activeClinicalObservationOrders Clinical query Active Clinical Observation Orders true study observation_order Active Clinical Orders date false false qcstate/publicdata This report contains a list of today's treatments to be administered +activeBehaviorObservationOrders Behavior query Active Behavior Observation Orders true study observation_order Active Behavior Orders date false false qcstate/publicdata This report contains a list of today's treatments to be administered +observationOrders Clinical query Observation Orders true study observation_order date false false qcstate/publicdata This report contains a list of today's treatments to be administered +alopecia Behavior query Alopecia Scores TRUE study clinical_observations Alopecia Scores date FALSE FALSE qcstate/publicdata This report contains the alopecia scores for the animal +behaviorCases Behavior query Active Behavior Cases true study activeBehaviorCases date false false qcstate/publicdata This displays active behavioral cases +allBehaviorCases Behavior query Behavior Cases true study behaviorCases date false false qcstate/publicdata This displays all behavioral cases +bloodSchedule +cases Clinical query Active Clinical Cases true study activeClinicalCases date false false qcstate/publicdata This displays active clinical cases +clinCases Clinical query All Clinical Cases true study clinicalCases date false false qcstate/publicdata This report contains one record for each clinical case +prcOrders Clinical query Procedure Orders true study prc_order_report date false false qcstate/publicdata This report contains one record for each procedure order +prcOverdue Daily Reports query Overdue Procedures true study prcOverdue date false false qcstate/publicdata This report contains one record for each overdue procedure +clinMedicationSchedule Daily Reports js Today's Medication Schedule true study clinMedicationSchedule date false false qcstate/publicdata This report contains a list of today's treatments to be administered +prcSchedule Daily Reports query Today's Procedure Schedule true study prcSchedule date false false qcstate/publicdata This report contains a list of today's procedures to be administered +dietSchedule +drug +incompleteTreatments Daily Reports js Incomplete Treatments true study incompleteTreatments date false false qcstate/publicdata This report contains a list of incomplete treatments for the previous 30 days +incompleteObservations Daily Reports js Incomplete Observations true study incompleteObservations date false false qcstate/publicdata This report contains a list of incomplete observations for the previous 30 days +pairingsBehavior +pairingHousingSummary +pairingSummary Behavior query Pairing Summary TRUE study pairingSummary date FALSE FALSE qcstate/publicdata This report displays animal pairings +activePairing Behavior query Active Pairing TRUE study pairingSummary Active Pairing date FALSE FALSE qcstate/publicdata This report displays animal pairings +pairingHistory +nhpTraining Behavior query Animal Training TRUE study nhpTraining date FALSE FALSE qcstate/publicdata This report displays animal training data +roommateHistoryBehavior +surgicalCases +surgMedicationSchedule +surgMedicationScheduleDaily +pairings +behaviorRemarks Behavior query Behavior Remarks true study BehaviorClinRemarks date false false qcstate/publicdata This report contains the behavior remarks entered about each animal +clinObsBehavior Behavior query Observations true study behaviorObservations date false false qcstate/publicdata This report contains one record for each encounter with each animal, including surergies, exams, procedures, etc. +clinremarks Clinical query Clinical Remarks true study ClinicalClinRemarks date false false qcstate/publicdata This report contains the clinical remarks entered about each animal +physicalExam Clinical query Exam History True study physicalExam date false false qcstate/publicdata This report displays physical exam data for the selected animal +historicalOther General query Historical True study historicalOther date false false qcstate/publicdata This report displays historical events from legacy systems \ No newline at end of file diff --git a/nbri_ehr/resources/schemas/dbscripts/postgresql/nbri_ehr-0.000-25.001.sql b/nbri_ehr/resources/schemas/dbscripts/postgresql/nbri_ehr-0.000-25.001.sql new file mode 100644 index 0000000..aa5dbcd --- /dev/null +++ b/nbri_ehr/resources/schemas/dbscripts/postgresql/nbri_ehr-0.000-25.001.sql @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +CREATE SCHEMA nbri_ehr; + +CREATE TABLE nbri_ehr.LocationTypes +( + RowId SERIAL NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + Container entityId NOT NULL, + + NAME TEXT, + LocationTypeId INTEGER, + + CONSTRAINT PK_LocationTypes PRIMARY KEY (RowId), + CONSTRAINT FK_LocationTypes_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_nbri_ehr_LocationTypes_Container ON nbri_ehr.LocationTypes (Container); + +CREATE TABLE nbri_ehr.Locations +( + RowId SERIAL NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + Container entityId NOT NULL, + + NAME TEXT, + LocationId INTEGER, + LocationType INTEGER, + + CONSTRAINT PK_Locations PRIMARY KEY (RowId), + CONSTRAINT FK_Locations_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_nbri_ehr_Locations_Container ON nbri_ehr.Locations (Container); + +CREATE TABLE nbri_ehr.LocationsMapping +( + RowId SERIAL NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + Container entityId NOT NULL, + + ParentLocation INTEGER, + ChildLocation INTEGER, + NAME TEXT, + + CONSTRAINT PK_LocationsMapping PRIMARY KEY (RowId), + CONSTRAINT FK_LocationsMapping_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_nbri_ehr_LocationsMapping_Container ON nbri_ehr.LocationsMapping (Container); + +CREATE TABLE nbri_ehr.Staff +( + staffId INTEGER NOT NULL, + email TEXT, + firstName TEXT, + lastName TEXT, + middleName TEXT, + displayName TEXT, + hireDate TIMESTAMP, + lastEmployDate TIMESTAMP, + officePhone TEXT, + officePhoneExt TEXT, + officeFax TEXT, + homePhone TEXT, + beeperPhone TEXT, + cellPhone TEXT, + emergencyContact TEXT, + emergencyPhone TEXT, + homeAddress1 TEXT, + homeAddress2 TEXT, + homeCity TEXT, + homeState TEXT, + homeZip TEXT, + homeZipExt TEXT, + homeCountry TEXT, + officeAddress1 TEXT, + officeAddress2 TEXT, + officeCity TEXT, + officeState TEXT, + officeZip TEXT, + officeZipExt TEXT, + officeCountry TEXT, + birthDate TIMESTAMP, + hsName TEXT, + collegeGradDate TEXT, + collegeDegree TEXT, + collegeMajor TEXT, + collegeName TEXT, + supervisor INTEGER, + positionName TEXT, + positionDesc TEXT, + active BOOLEAN, + Container entityId NOT NULL, + CONSTRAINT PK_STAFF PRIMARY KEY (staffId), + CONSTRAINT FK_STAFF_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_nbri_ehr_Staff_Container ON nbri_ehr.Staff (Container); + +CREATE TABLE nbri_ehr.Lot +( + LotId INTEGER, + AnimalShipment INTEGER, + Date TIMESTAMP, + LotSequence INTEGER, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_LOT PRIMARY KEY (LotId), + CONSTRAINT FK_LOT_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Lot_Container ON nbri_ehr.Lot (Container); + +CREATE TABLE nbri_ehr.AnimalShipment +( + AnimalShipmentId INTEGER, + ReceivedByStaff USERID, + Cage TEXT, + Room TEXT, + Building TEXT, + Area TEXT, + AnimalDelivery INTEGER, + LotNumber INTEGER, + ReceivedDate TIMESTAMP, + BirthDate TIMESTAMP, + MalesReceived INTEGER, + FemalesReceived INTEGER, + EitherReceived INTEGER, + CanUnreceive BOOLEAN, + CostCenter INTEGER, + Dam TEXT, + Sire TEXT, + RecordedDate TIMESTAMP, + RecordedBy TEXT, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_ANIMALSHIPMENT PRIMARY KEY (AnimalShipmentId), + CONSTRAINT FK_ANIMALSHIPMENT_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Animal_Shipment_Container ON nbri_ehr.AnimalShipment (Container); + +CREATE TABLE nbri_ehr.AnimalDelivery +( + AnimalDeliveryId INTEGER, + AnimalShipment INTEGER, + ShipTo INTEGER, + cage TEXT, + room TEXT, + building TEXT, + area TEXT, + AnimalReqOrder INTEGER, + DeliveryState INTEGER, + DeliveryNumber INTEGER, + ExpectedDate TIMESTAMP, + Project INTEGER, + BillToAccount INTEGER, + BillToStaff USERID, + PerDiemAccount INTEGER, + PerDiemStaff USERID, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_ANIMALDELIVERY PRIMARY KEY (AnimalDeliveryId), + CONSTRAINT FK_ANIMALDELIVER_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Animal_Delivery_Container ON nbri_ehr.AnimalDelivery (Container); + +CREATE TABLE nbri_ehr.AnimalDeliveryEsig +( + EsigId INTEGER, + AnimalDelivery INTEGER, + EsigEvent INTEGER, + UserProfile USERID, + EsigDateTime TIMESTAMP, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_ANIMALDELIVERYESIG PRIMARY KEY (EsigId), + CONSTRAINT FK_ANIMALDELIVERESIG_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Animal_Delivery_Esig_Container ON nbri_ehr.AnimalDeliveryEsig (Container); + +CREATE TABLE nbri_ehr.AnimalReqOrder +( + AnimalReqOrderId INTEGER, + AnimalVendor INTEGER, + RequisitionerStaff USERID, + RequestNumber TEXT, + RequisitionNumber TEXT, + Bill BOOLEAN, + ShippingContact TEXT, + CreateDate TIMESTAMP, + ReqOrderType INTEGER, + ReqOrderState INTEGER, + BillToAccount INTEGER, + BillToStaff USERID, + PerDiemAccount INTEGER, + PerDiemStaff USERID, + SubmittedByStaff USERID, + ApprovedByStaff USERID, + SubmittedDate TIMESTAMP, + ApprovedDate TIMESTAMP, + Segment INTEGER, + Project INTEGER, + SiteCage TEXT, + SiteRoom TEXT, + SiteBuilding TEXT, + SiteArea TEXT, + CreatedByStaff USERID, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_ANIMALREQORDER PRIMARY KEY (AnimalReqOrderId), + CONSTRAINT FK_ANIMALREQORDER_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Animal_Req_Order_Container ON nbri_ehr.AnimalReqOrder (Container); + +CREATE TABLE nbri_ehr.AnimalReqOrderEsig +( + EsigId INTEGER, + AnimalReqOrder INTEGER, + EsigEvent INTEGER, + UserProfile USERID, + EsigDateTime TIMESTAMP, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_ANIMALREQORDERESIG PRIMARY KEY (EsigId), + CONSTRAINT FK_ANIMALREQORDERESIG_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Animal_Req_Order_Esig_Container ON nbri_ehr.AnimalReqOrderEsig (Container); + +CREATE TABLE nbri_ehr.AnimalVendor +( + AnimalVendorId INTEGER, + VendorApprovalCode INTEGER, + VendorName TEXT, + StreetAddress1 TEXT, + StreetAddress2 TEXT, + City TEXT, + StateProv TEXT, + Country TEXT, + Zip TEXT, + ZipExt TEXT, + PhoneNumber TEXT, + FaxNumber TEXT, + Comments TEXT, + InternalVendor TEXT, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_ANIMALVENDOR PRIMARY KEY (AnimalVendorId), + CONSTRAINT FK_ANIMALVENDOR_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Animal_Vendor_Container ON nbri_ehr.AnimalVendor (Container); + +CREATE TABLE nbri_ehr.ShipTo +( + ShipToId INTEGER, + Name TEXT, + Country TEXT, + City TEXT, + StreetAddress1 TEXT, + StreetAddress2 TEXT, + StateProv TEXT, + Zip TEXT, + ZipExt TEXT, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_SHIPTO PRIMARY KEY (ShipToId), + CONSTRAINT FK_SHIPTO_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Ship_To_Container ON nbri_ehr.ShipTo (Container); + +ALTER TABLE nbri_ehr.Staff + ADD COLUMN Created TIMESTAMP, + ADD COLUMN CreatedBy USERID, + ADD COLUMN Modified TIMESTAMP, + ADD COLUMN ModifiedBy USERID; + +CREATE TABLE nbri_ehr.ProtocolEsig +( + EsigId INTEGER, + Protocol INTEGER, + EsigEvent INTEGER, + UserProfile USERID, + EsigDateTime TIMESTAMP, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_PROTOCOLESIG PRIMARY KEY (EsigId), + CONSTRAINT FK_PROTOCOLESIG_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Protocol_Esig_Container ON nbri_ehr.ProtocolEsig (Container); + +CREATE TABLE nbri_ehr.ProtocolUsage +( + Protocol TEXT, + UserReferenceNumber TEXT, + ShortTitle TEXT, + Investigator TEXT, + ProtocolType TEXT, + CurrentState TEXT, + SubmitDate TIMESTAMP, + ApprovalDate TIMESTAMP, + ExpirationDate TIMESTAMP, + EffectiveDate TIMESTAMP, + RenewalDate TIMESTAMP, + AuthorizedAmt FLOAT, + OnOrderAmt FLOAT, + UsedAmt FLOAT, + AvailableAmt FLOAT, + PercentLeft FLOAT, + SegmentId INTEGER, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT FK_PROTOCOLUSAGE_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Protocol_Usage_Container ON nbri_ehr.ProtocolUsage (Container); + +CREATE TABLE nbri_ehr.Account +( + AccountId INTEGER, + AccountNumber TEXT, + Department INTEGER, + CostType INTEGER, + ExpenseClass INTEGER, + ProjectCode INTEGER, + Description TEXT, + Active BOOLEAN, + Cage TEXT, + Room TEXT, + Building TEXT, + Area TEXT, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_ACCOUNT PRIMARY KEY (AccountId), + CONSTRAINT FK_ACCOUNT_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Account_Container ON nbri_ehr.Account (Container); + + +CREATE TABLE nbri_ehr.Department +( + DepartmentId INTEGER, + Name TEXT, + Description TEXT, + ParentDepartment INTEGER, + Staff USERID, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_DEPARTMENT PRIMARY KEY (DepartmentId), + CONSTRAINT FK_DEPARTMENT_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Department_Container ON nbri_ehr.Department (Container); + +ALTER TABLE nbri_ehr.AnimalShipment ADD COLUMN Floor VARCHAR; +ALTER TABLE nbri_ehr.AnimalDelivery ADD COLUMN Floor VARCHAR; + +CREATE TABLE nbri_ehr.IdHistory +( + Id VARCHAR, + Name VARCHAR, + Type INTEGER, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_IDHISTORY PRIMARY KEY (Id, Name), + CONSTRAINT FK_IDHISTORY_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_ID_History_Container ON nbri_ehr.IdHistory (Container); + +CREATE TABLE nbri_ehr.DeletedRecord +( + Id INTEGER, + Protocol VARCHAR, + UserReferenceNumber VARCHAR, + Investigator VARCHAR, + Title VARCHAR, + EsigEvent INTEGER, + EsigUser USERID, + EsigDate TIMESTAMP, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_DELETEDRECORD PRIMARY KEY (Id), + CONSTRAINT FK_DELETEDRECORD_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Deleted_Record_Container ON nbri_ehr.DeletedRecord (Container); + +CREATE TABLE nbri_ehr.Question +( + QuestionId INTEGER, + Type VARCHAR, + Text VARCHAR, + CreationDate TIMESTAMP, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_QUESTION PRIMARY KEY (QuestionId), + CONSTRAINT FK_QUESTION_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Question_Container ON nbri_ehr.Question (Container); + +CREATE TABLE nbri_ehr.QuestionResponse +( + QuestionResponseId INTEGER, + Protocol INTEGER, + Response VARCHAR, + Question INTEGER, + Questionnaire INTEGER, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_QUESTIONRESPONSE PRIMARY KEY (QuestionResponseId), + CONSTRAINT FK_QUESTIONRESPONSE_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Question_Response_Container ON nbri_ehr.QuestionResponse (Container); + +ALTER TABLE nbri_ehr.AnimalVendor ADD COLUMN VendorProductionLocation INTEGER; + +ALTER TABLE nbri_ehr.ProtocolUsage DROP COLUMN SegmentId; +ALTER TABLE nbri_ehr.ProtocolUsage ADD COLUMN Species integer; + +ALTER TABLE nbri_ehr.AnimalReqOrder DROP COLUMN Segment; +ALTER TABLE nbri_ehr.AnimalReqOrder ADD COLUMN Protocol integer; +ALTER TABLE nbri_ehr.AnimalReqOrder ADD COLUMN Species integer; + +ALTER TABLE nbri_ehr.Account DROP COLUMN cage; +ALTER TABLE nbri_ehr.Account DROP COLUMN room; +ALTER TABLE nbri_ehr.Account DROP COLUMN building; + +CREATE TABLE nbri_ehr.ProtocolStress +( + RowId SERIAL NOT NULL, + Protocol INTEGER, + Species VARCHAR, + Stress INTEGER, + Allowed INTEGER, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_PROTOCOLSTRESS PRIMARY KEY (RowId), + CONSTRAINT FK_PROTOCOLSTRESS_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_ProtocolStress_Container ON nbri_ehr.ProtocolStress (Container); + +CREATE TABLE nbri_ehr.Stress +( + StressId INTEGER, + Name VARCHAR, + Description VARCHAR, + Ranking INTEGER, + RegulatoryStressLevel INTEGER, + Active BOOLEAN, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_STRESS PRIMARY KEY (StressId), + CONSTRAINT FK_STRESS_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Stress_Container ON nbri_ehr.Stress (Container); + +CREATE TABLE nbri_ehr.ProtocolProcedures +( + RowId SERIAL NOT NULL, + Protocol INTEGER, + Species VARCHAR, + Procedure VARCHAR, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_PROTOCOLPROCEDURES PRIMARY KEY (RowId), + CONSTRAINT FK_PROTOCOLPROCEDURES_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_ProtocolProcedures_Container ON nbri_ehr.ProtocolProcedures (Container); + +CREATE TABLE nbri_ehr.CageCard +( + CageCardId INTEGER, + Protocol INTEGER, + Species INTEGER, + CardFormat INTEGER, + CostCenter INTEGER, + GenerationDate TIMESTAMP, + UpdateDate TIMESTAMP, + NumberOfAnimals INTEGER, + Cage INTEGER, + Room INTEGER, + Floor INTEGER, + Building INTEGER, + Area INTEGER, + Account INTEGER, + AccountStaff USERID, + CensusActivityStatus VARCHAR, + CensusActivityDate TIMESTAMP, + AnimalDelivery INTEGER, + AnimalRequestedByStaff USERID, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_CAGECARD PRIMARY KEY (CageCardId), + CONSTRAINT FK_CAGECARD_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Cage_Card_Container ON nbri_ehr.CageCard (Container); + +CREATE TABLE nbri_ehr.CageCardHistory +( + RowId SERIAL NOT NULL, + CageCardId INTEGER, + AnimalDelivery INTEGER, + Protocol INTEGER, + Species INTEGER, + CardFormat INTEGER, + CostCenter INTEGER, + GenerationDate TIMESTAMP, + UpdateDate TIMESTAMP, + NumberOfAnimals INTEGER, + Cage INTEGER, + Room INTEGER, + Floor INTEGER, + Building INTEGER, + Area INTEGER, + Account INTEGER, + AccountStaff USERID, + CensusActivityStatus VARCHAR, + CensusActivityDate TIMESTAMP, + CensusStartDate TIMESTAMP, + CensusStopDate TIMESTAMP, + TransferDate TIMESTAMP, + ActionDate TIMESTAMP, + RetrospectiveStress INTEGER, + AnimalRequestedByStaff USERID, + Container entityId NOT NULL, + Created TIMESTAMP, + CreatedBy USERID, + Modified TIMESTAMP, + ModifiedBy USERID, + CONSTRAINT PK_CAGECARDHISTORY PRIMARY KEY (RowId), + CONSTRAINT FK_CAGECARDHISTORY_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId) +); +CREATE INDEX IX_Nbri_Ehr_Cage_Card_History_Container ON nbri_ehr.CageCardHistory (Container); diff --git a/nbri_ehr/resources/schemas/nbri_ehr.xml b/nbri_ehr/resources/schemas/nbri_ehr.xml new file mode 100644 index 0000000..e4cf435 --- /dev/null +++ b/nbri_ehr/resources/schemas/nbri_ehr.xml @@ -0,0 +1,572 @@ + + + + + Location Types + DETAILED + + + + + + + + + + +
+ + + Locations + DETAILED + + + + + + + + + + + +
+ + + Locations Mapping + DETAILED + + + + + + + + + + + +
+ + + Staff + DETAILED + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Lot + DETAILED + + + + + + + + + + + +
+ + + Animal Shipment + DETAILED + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Animal Delivery + DETAILED + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Animal Delivery ESignature + DETAILED + + + + + + + + + + + + +
+ + + Animal Req Order + DETAILED + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Animal Req Order ESignature + DETAILED + + + + + + + + + + + + +
+ + + Animal Vendor + DETAILED + + + + + + + + + + + + + + + + + + + + + + +
+ + + Ship To + DETAILED + + + + + + + + + + + + + + + + +
+ + + Protocol ESignature + DETAILED + + + + + + + + + + + + +
+ + + Protocol Usage + DETAILED + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Account + DETAILED + + + + + + + + + + + + + + + + +
+ + + Department + DETAILED + + + + + + + + + + + + +
+ + + Id History + DETAILED + + + + + + + + + + +
+ + + Deleted Record + DETAILED + + + + + + + + + + + + + + + +
+ + + Question + DETAILED + + + + + + + + + + + +
+ + + Question Response + DETAILED + + + + + + + + + + + + +
+ + + Protocol Stress + DETAILED + + + + + + + + + + + + +
+ + + Stress + DETAILED + + + + + + + + + + + + + +
+ + + Protocol Procedures + DETAILED + + + + + + + + + + + +
+ + + Cage Card + DETAILED + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Cage Card History + DETAILED + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
\ No newline at end of file diff --git a/nbri_ehr/resources/scripts/nbri_triggers.js b/nbri_ehr/resources/scripts/nbri_triggers.js new file mode 100644 index 0000000..e4ad95b --- /dev/null +++ b/nbri_ehr/resources/scripts/nbri_triggers.js @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +var console = require("console"); +var LABKEY = require("labkey"); + +// For more complicated logic, I highly recommend implementing this in java. This provides much better debugging, and the full use of the server-side java APIs +// Methods on this TriggerHelper can be called from JS, and can return values to the JS code. In general, I try to only pass primitives; however, that may not always be required + +// NOTE: NBRI specific script options should be set here in INIT triggers + +exports.init = function (EHR) { + + + EHR.Server.TriggerManager.registerHandler(EHR.Server.TriggerManager.Events.INIT, function (event, helper, EHR) { + + EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('ehr_lookups', 'cage', EHR.Server.TriggerManager.Events.BEFORE_UPSERT); + EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('ehr_lookups', 'procedures', EHR.Server.TriggerManager.Events.BEFORE_DELETE); + EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('study', 'assignment', EHR.Server.TriggerManager.Events.BEFORE_UPSERT); + EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('study', 'clinremarks', EHR.Server.TriggerManager.Events.BEFORE_UPSERT); + EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('study', 'clinremarks', EHR.Server.TriggerManager.Events.AFTER_UPSERT); + EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('study', 'blood', EHR.Server.TriggerManager.Events.BEFORE_UPSERT); + EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('study', 'cases', EHR.Server.TriggerManager.Events.AFTER_UPSERT); + EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('study', 'cases', EHR.Server.TriggerManager.Events.AFTER_DELETE); + + helper.setScriptOptions({ + datasetsToClose: ['assignment', 'protocolAssignment' , 'housing', 'treatment_order', 'observation_order', 'cases', 'pairings', 'exemptions', 'flags'] + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'arrival', function(event, helper) { + helper.setScriptOptions({ + allowAnyId: true, + requiresStatusRecalc: false, // set in upsert to handle rearrival + allowDatesInDistantPast: true, + skipAssignmentCheck: true, + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'protocolAssignment', function(event, helper) { + helper.setScriptOptions({ + allowAnyId: false, + requiresStatusRecalc: false, + allowDatesInDistantPast: true + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'assignment', function(event, helper) { + helper.setScriptOptions({ + allowAnyId: false, + requiresStatusRecalc: false, + allowDatesInDistantPast: true, + skipAssignmentCheck: true, + removeTimeFromDate: false, + doStandardProtocolCountValidation: false + }); + + helper.decodeExtraContextProperty('assignmentsInTransaction', []); + + helper.registerRowProcessor(function(helper, row){ + if (!row) + return; + + if (!row.Id || !row.project){ + return; + } + + var assignmentsInTransaction = helper.getProperty('assignmentsInTransaction'); + assignmentsInTransaction = assignmentsInTransaction || []; + + var shouldAdd = true; + if (row.objectid){ + LABKEY.ExtAdapter.each(assignmentsInTransaction, function(r){ + if (r.objectid === row.objectid){ + shouldAdd = false; + return false; + } + }, this); + } + + if (shouldAdd){ + assignmentsInTransaction.push({ + Id: row.Id, + objectid: row.objectid, + date: row.date, + enddate: row.enddate, + qcstate: row.QCState, + project: row.project + }); + } + + helper.setProperty('assignmentsInTransaction', assignmentsInTransaction); + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'alias', function(event, helper) { + helper.setScriptOptions({ + allowDatesInDistantPast: true, + removeTimeFromDate: false, + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'drug', function(event, helper) { + helper.setScriptOptions({ + allowDeadIds: true, + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'treatment_order', function(event, helper) { + helper.setScriptOptions({ + allowFutureDates: true, + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'observation_order', function(event, helper, EHR) { + helper.setScriptOptions({ + allowFutureDates: true, + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'deaths', function(event, helper) { + + helper.setScriptOptions({ + datasetsToClose: ['assignment', 'protocolAssignment' , 'housing', 'treatment_order', 'observation_order', 'cases', 'pairings', 'exemptions', 'flags'], + allowShippedIds: false, + allowDeadIds: false, + requiresStatusRecalc: true, + allowRequestsInPast: true, + removeTimeFromDate: false, + allowDatesInDistantPast: true, + allowAnyId: true + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'necropsy', function(event, helper) { + + helper.setScriptOptions({ + removeTimeFromDate: false + }); + }); + + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'cases', function(event, helper) { + helper.setScriptOptions({ + allowDatesInDistantPast: true + }); + }); +} diff --git a/nbri_ehr/resources/views/NBRI_amimalHistory.webpart.xml b/nbri_ehr/resources/views/NBRI_amimalHistory.webpart.xml new file mode 100644 index 0000000..ad91414 --- /dev/null +++ b/nbri_ehr/resources/views/NBRI_amimalHistory.webpart.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/acquisitionReport.html b/nbri_ehr/resources/views/acquisitionReport.html new file mode 100644 index 0000000..f1ecf91 --- /dev/null +++ b/nbri_ehr/resources/views/acquisitionReport.html @@ -0,0 +1,217 @@ + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ +
+
+
+ + diff --git a/nbri_ehr/resources/views/acquisitionReport.view.xml b/nbri_ehr/resources/views/acquisitionReport.view.xml new file mode 100644 index 0000000..bbbab5f --- /dev/null +++ b/nbri_ehr/resources/views/acquisitionReport.view.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/animalHistory.html b/nbri_ehr/resources/views/animalHistory.html new file mode 100644 index 0000000..5c2c43a --- /dev/null +++ b/nbri_ehr/resources/views/animalHistory.html @@ -0,0 +1,107 @@ + diff --git a/nbri_ehr/resources/views/animalHistory.view.xml b/nbri_ehr/resources/views/animalHistory.view.xml new file mode 100644 index 0000000..885cf5f --- /dev/null +++ b/nbri_ehr/resources/views/animalHistory.view.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/begin.html b/nbri_ehr/resources/views/begin.html new file mode 100644 index 0000000..0987b92 --- /dev/null +++ b/nbri_ehr/resources/views/begin.html @@ -0,0 +1,251 @@ + \ No newline at end of file diff --git a/nbri_ehr/resources/views/begin.view.xml b/nbri_ehr/resources/views/begin.view.xml new file mode 100644 index 0000000..2132d52 --- /dev/null +++ b/nbri_ehr/resources/views/begin.view.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/begin.webpart.xml b/nbri_ehr/resources/views/begin.webpart.xml new file mode 100644 index 0000000..6082de1 --- /dev/null +++ b/nbri_ehr/resources/views/begin.webpart.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/cageDetails.html b/nbri_ehr/resources/views/cageDetails.html new file mode 100644 index 0000000..a0c5da2 --- /dev/null +++ b/nbri_ehr/resources/views/cageDetails.html @@ -0,0 +1,83 @@ + \ No newline at end of file diff --git a/nbri_ehr/resources/views/cageDetails.view.xml b/nbri_ehr/resources/views/cageDetails.view.xml new file mode 100644 index 0000000..68b5372 --- /dev/null +++ b/nbri_ehr/resources/views/cageDetails.view.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/clinicalHistoryExport.html b/nbri_ehr/resources/views/clinicalHistoryExport.html new file mode 100644 index 0000000..8aff7e7 --- /dev/null +++ b/nbri_ehr/resources/views/clinicalHistoryExport.html @@ -0,0 +1,86 @@ +
+ National Biomedical Research Institute at UC Davis
Animal Record
+
+ + \ No newline at end of file diff --git a/nbri_ehr/resources/views/clinicalHistoryExport.view.xml b/nbri_ehr/resources/views/clinicalHistoryExport.view.xml new file mode 100644 index 0000000..35f09e3 --- /dev/null +++ b/nbri_ehr/resources/views/clinicalHistoryExport.view.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/datasets.html b/nbri_ehr/resources/views/datasets.html new file mode 100644 index 0000000..f6a4150 --- /dev/null +++ b/nbri_ehr/resources/views/datasets.html @@ -0,0 +1,130 @@ + diff --git a/nbri_ehr/resources/views/datasets.view.xml b/nbri_ehr/resources/views/datasets.view.xml new file mode 100644 index 0000000..895d3d0 --- /dev/null +++ b/nbri_ehr/resources/views/datasets.view.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/enterData.html b/nbri_ehr/resources/views/enterData.html new file mode 100644 index 0000000..2d9c84f --- /dev/null +++ b/nbri_ehr/resources/views/enterData.html @@ -0,0 +1,43 @@ +
+ + diff --git a/nbri_ehr/resources/views/enterData.view.xml b/nbri_ehr/resources/views/enterData.view.xml new file mode 100644 index 0000000..a2ae43f --- /dev/null +++ b/nbri_ehr/resources/views/enterData.view.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/nbri_login.html b/nbri_ehr/resources/views/nbri_login.html new file mode 100644 index 0000000..30a475a --- /dev/null +++ b/nbri_ehr/resources/views/nbri_login.html @@ -0,0 +1,48 @@ +
+
Sign In
+
+
+ + + + + + Remember my email address + + +
+ + + + +
+ + + + + +
+
+ + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/nbri_login.view.xml b/nbri_ehr/resources/views/nbri_login.view.xml new file mode 100644 index 0000000..ec29417 --- /dev/null +++ b/nbri_ehr/resources/views/nbri_login.view.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/necropsy.html b/nbri_ehr/resources/views/necropsy.html new file mode 100644 index 0000000..9952555 --- /dev/null +++ b/nbri_ehr/resources/views/necropsy.html @@ -0,0 +1,98 @@ + + +
+ National Biomedical Research Institute at UC Davis
Necropsy
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ + diff --git a/nbri_ehr/resources/views/necropsy.view.xml b/nbri_ehr/resources/views/necropsy.view.xml new file mode 100644 index 0000000..e10c578 --- /dev/null +++ b/nbri_ehr/resources/views/necropsy.view.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/nbri_ehr/resources/views/participantView.html b/nbri_ehr/resources/views/participantView.html new file mode 100644 index 0000000..89f88bf --- /dev/null +++ b/nbri_ehr/resources/views/participantView.html @@ -0,0 +1,31 @@ + \ No newline at end of file diff --git a/nbri_ehr/resources/views/participantView.view.xml b/nbri_ehr/resources/views/participantView.view.xml new file mode 100644 index 0000000..c41ebae --- /dev/null +++ b/nbri_ehr/resources/views/participantView.view.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbri_ehr/resources/web/ehr/metadata/Default.js b/nbri_ehr/resources/web/ehr/metadata/Default.js new file mode 100644 index 0000000..ba9ff26 --- /dev/null +++ b/nbri_ehr/resources/web/ehr/metadata/Default.js @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + + +EHR.model.DataModelManager.registerMetadata('Default', { + byQuery: { + 'study.MHC': { + QCState: { + getInitialValue: function(v){ + var qc; + if (!v && EHR.Security.getQCStateByLabel('Completed')) + qc = EHR.Security.getQCStateByLabel('Completed').RowId; + return v || qc; + }, + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/ProcedureOrderCompleteButton.js b/nbri_ehr/resources/web/nbri_ehr/buttons/ProcedureOrderCompleteButton.js new file mode 100644 index 0000000..c5969bd --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/ProcedureOrderCompleteButton.js @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.namespace('NBRI_EHR.ProcedureOrderCompleteButton'); + +Ext4.define('NBRI_EHR.window.ProcedureOrderCompleteWindow', { + extend: 'Ext.window.Window', + returnLocation: null, + + initComponent: function() { + Ext4.apply(this, { + title: 'Mark Procedure Order Completed', + modal: true, + width: 450, + bodyStyle: 'padding: 5px;', + closeAction: 'destroy', + items: [{ + xtype: 'panel', + border: false, + html: '

This will mark the procedure order(s) completed without entering a procedure. Ensure the procedure has been entered separately if it should be recorded.

', + }], + buttons: [{ + text:'Submit', + scope: this, + handler: function (btn) { + this.recordProcedure(btn, this.dataRegion); + } + },{ + text: 'Cancel', + scope: this, + handler: function(btn){ + btn.up('window').close(); + } + }] + }); + + this.callParent(arguments); + }, + + recordProcedure: function(btn, dataRegion) { + let win = btn.up('window'); + const selectedRows = [...new Set(dataRegion.getChecked())]; + var me = this; + btn.setDisabled(true); + Ext4.Msg.wait('Completing procedure orders...'); + + LABKEY.Query.selectRows({ + schemaName: 'core', + queryName: 'QCState', + filterArray: [LABKEY.Filter.create('label', 'Completed', LABKEY.Filter.Types.EQUALS)], + scope: this, + ignoreFilter: true, + columns: 'RowId', + success: function (data) { + const rowsToInsert = []; + const completedRowId = data?.rows?.[0]?.RowId; + if (completedRowId) { + for (const row of selectedRows) { + rowsToInsert.push({ + lsid: row, + qcstate: completedRowId + }); + } + } + + LABKEY.Query.updateRows({ + schemaName: 'study', + queryName: 'prc_order', + rows: rowsToInsert, + scope: this, + success: function() { + Ext4.Msg.alert('Success', 'Procedure order(s) marked completed.', function(){ + dataRegion.clearSelected(); + window.location = me.returnLocation; + window.location.reload(); + }); + win.close(); + }, + failure: function(error) { + btn.setDisabled(false); + Ext4.Msg.alert('Error', error?.exception ?? 'An error occurred while recording procedure orders.'); + console.error(error); + } + }); + }, + failure: function(error) { + btn.setDisabled(false); + Ext4.Msg.alert('Error', error?.exception ?? 'An error occurred querying qcstates.'); + console.error(error); + } + }); + } + +}); + +NBRI_EHR.ProcedureOrderCompleteButton = new function () { + return { + procedureOrderCompleteHandler: function(dataRegion) { + if (dataRegion && dataRegion.getChecked().length > 0) { + Ext4.create('NBRI_EHR.window.ProcedureOrderCompleteWindow', { + dataRegion: dataRegion, + returnLocation: window.location.href + }).show(); + } + else { + Ext4.Msg.alert('Error', 'Please select at least one procedure order.'); + } + }, + } +} diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/RecordProcedureButton.js b/nbri_ehr/resources/web/nbri_ehr/buttons/RecordProcedureButton.js new file mode 100644 index 0000000..a8d8c85 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/RecordProcedureButton.js @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.namespace('NBRI_EHR.RecordProcedureButton'); + +Ext4.define('NBRI_EHR.window.RecordProcedureWindow', { + extend: 'Ext.window.Window', + returnLocation: null, + + initComponent: function() { + Ext4.apply(this, { + title: 'Record Procedures', + modal: true, + width: 450, + bodyStyle: 'padding: 5px;', + closeAction: 'destroy', + items: [{ + xtype: 'labkey-combo', + fieldLabel: 'Performed By', + width: 350, + labelWidth: 100, + value: LABKEY.Security.currentUser.id, + itemId: 'performedBy', + displayField: 'DisplayName', + valueField: 'UserId', + queryMode: 'local', + forceSelection: true, + matchFieldWidth: false, + store: { + type: 'labkey-store', + schemaName: 'core', + queryName: 'PrincipalsWithoutAdmin', + columns: 'UserId,DisplayName,FirstName,LastName', + sort: 'Type,DisplayName', + autoLoad: true + }, + anyMatch: true, + caseSensitive: false, + }, { + xtype: 'xdatetime', + itemId: 'dateField', + width: 350, + labelWidth: 100, + fieldLabel: 'Date', + allowBlank: false, + name: 'date', + value: new Date() + },], + buttons: [{ + text:'Submit', + scope: this, + handler: function (btn) { + this.recordProcedure(btn, this.dataRegion); + } + },{ + text: 'Cancel', + scope: this, + handler: function(btn){ + btn.up('window').close(); + } + }] + }); + + this.callParent(arguments); + }, + + recordProcedure: function(btn, dataRegion) { + let win = btn.up('window'); + let windDate = win.down('#dateField').getValue(); + let performedBy = win.down('#performedBy').getValue(); + const selectedRows = [...new Set(dataRegion.getChecked())]; + var me = this; + btn.setDisabled(true); + Ext4.Msg.wait('Recording procedures...'); + + LABKEY.Query.selectRows({ + schemaName: 'study', + queryName: 'prc_order', + filterArray: [LABKEY.Filter.create('lsid', selectedRows.join(';'), LABKEY.Filter.Types.EQUALS_ONE_OF)], + scope: this, + ignoreFilter: true, + columns: 'Id,objectid,procedure,category,caseid,orderedby,lsid', + success: function (data) { + const rowsToInsert = []; + Ext4.each(data.rows, function(row) { + Ext4.each(selectedRows, function(selectedRow) { + if (row.lsid === selectedRow) { + rowsToInsert.push({ + Id: row.Id, + procedure: row.procedure, + orderid: row.objectid, + date: windDate, + performedby: performedBy, + objectid: LABKEY.Utils.generateUUID(), + orderedby: row.orderedby, + category: row.category, + caseid: row.caseid + }); + } + }); + }); + + LABKEY.Query.insertRows({ + schemaName: 'study', + queryName: 'prc', + rows: rowsToInsert, + scope: this, + success: function() { + Ext4.Msg.alert('Success', 'Procedures recorded successfully.', function(){ + dataRegion.clearSelected(); + window.location = me.returnLocation; + window.location.reload(); + }); + win.close(); + }, + failure: function(error) { + btn.setDisabled(false); + Ext4.Msg.alert('Error', error?.exception ?? 'An error occurred while recording procedures.'); + console.error(error); + } + }); + }, + failure: function(error) { + btn.setDisabled(false); + Ext4.Msg.alert('Error', error?.exception ?? 'An error occurred querying procedures.'); + console.error(error); + } + }); + } + +}); + +NBRI_EHR.RecordProcedureButton = new function () { + return { + recordProceduresHandler: function(dataRegion) { + if (dataRegion && dataRegion.getChecked().length > 0) { + Ext4.create('NBRI_EHR.window.RecordProcedureWindow', { + dataRegion: dataRegion, + returnLocation: window.location.href + }).show(); + } + else { + Ext4.Msg.alert('Error', 'Please select at least one procedure.'); + } + }, + } +} diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/RecordTreatmentButton.js b/nbri_ehr/resources/web/nbri_ehr/buttons/RecordTreatmentButton.js new file mode 100644 index 0000000..a5c800f --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/RecordTreatmentButton.js @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.namespace('NBRI_EHR.RecordTreatmentButton'); + +Ext4.define('NBRI_EHR.window.RecordTreatmentWindow', { + extend: 'Ext.window.Window', + returnLocation: null, + + initComponent: function() { + Ext4.apply(this, { + title: 'Bulk Record Treatments', + modal: true, + width: 450, + bodyStyle: 'padding: 5px;', + closeAction: 'destroy', + items: [{ + xtype: 'labkey-combo', + fieldLabel: 'Performed By', + width: 350, + labelWidth: 100, + value: LABKEY.Security.currentUser.id, + itemId: 'performedBy', + displayField: 'DisplayName', + valueField: 'UserId', + queryMode: 'local', + forceSelection: true, + matchFieldWidth: false, + store: { + type: 'labkey-store', + schemaName: 'core', + queryName: 'PrincipalsWithoutAdmin', + columns: 'UserId,DisplayName,FirstName,LastName', + sort: 'Type,DisplayName', + autoLoad: true + }, + anyMatch: true, + caseSensitive: false, + }, { + xtype: 'xdatetime', + itemId: 'dateField', + width: 350, + labelWidth: 100, + fieldLabel: 'Date', + allowBlank: false, + name: 'date', + value: new Date() + },], + buttons: [{ + text:'Submit', + scope: this, + handler: function (btn) { + this.recordTreatment(btn, this.dataRegion); + } + },{ + text: 'Cancel', + scope: this, + handler: function(btn){ + btn.up('window').close(); + } + }] + }); + + this.callParent(arguments); + }, + + recordTreatment: function(btn, dataRegion) { + let win = btn.up('window'); + let windDate = win.down('#dateField').getValue(); + let performedBy = win.down('#performedBy').getValue(); + const selectedRows = [...new Set(dataRegion.getChecked())]; + const objectIds = selectedRows.map(row => row.split('-pkSeparator-')[0]); + var me = this; + btn.setDisabled(true); + Ext4.Msg.wait('Recording treatments...'); + + LABKEY.Query.selectRows({ + schemaName: 'study', + queryName: 'treatment_order', + filterArray: [LABKEY.Filter.create('objectid', objectIds.join(';'), LABKEY.Filter.Types.EQUALS_ONE_OF)], + scope: this, + ignoreFilter: true, + columns: 'Id,objectid,code,route,amount,amount_units,concentration,volume,vol_units,conc_units,dosage,dosage_units,orderedby,category,caseid', + success: function (data) { + const rowsToInsert = []; + Ext4.each(data.rows, function(row) { + let scheduledDate; + Ext4.each(selectedRows, function(selectedRow) { + const parts = selectedRow.split('-pkSeparator-'); + const objectId = parts[0]; + const date = parts[1]; + if (row.objectid === objectId) { + scheduledDate = date; + rowsToInsert.push({ + Id: row.Id, + treatmentid: row.objectid, + date: windDate, + performedby: performedBy, + objectid: LABKEY.Utils.generateUUID(), + scheduledDate: scheduledDate, + code: row.code, + route: row.route, + amount: row.amount, + amount_units: row.amount_units, + concentration: row.concentration, + conc_units: row.conc_units, + dosage: row.dosage, + dosage_units: row.dosage_units, + volume: row.volume, + vol_units: row.vol_units, + orderedby: row.orderedby, + category: row.category, + caseid: row.caseid + }); + } + }); + }); + + LABKEY.Query.insertRows({ + schemaName: 'study', + queryName: 'drug', + rows: rowsToInsert, + scope: this, + success: function() { + Ext4.Msg.alert('Success', 'Treatments recorded successfully.', function(){ + dataRegion.clearSelected(); + window.location = me.returnLocation; + window.location.reload(); + }); + win.close(); + }, + failure: function(error) { + btn.setDisabled(false); + Ext4.Msg.alert('Error', error?.exception ?? 'An error occurred while recording treatments.'); + console.error(error); + } + }); + }, + failure: function(error) { + btn.setDisabled(false); + Ext4.Msg.alert('Error', error?.exception ?? 'An error occurred querying treatments.'); + console.error(error); + } + }); + } + +}); + +NBRI_EHR.RecordTreatmentButton = new function () { + return { + recordTreatmentsHandler: function(dataRegion) { + if (dataRegion && dataRegion.getChecked().length > 0) { + Ext4.create('NBRI_EHR.window.RecordTreatmentWindow', { + dataRegion: dataRegion, + returnLocation: window.location.href + }).show(); + } + else { + Ext4.Msg.alert('Error', 'Please select at least one treatment.'); + } + }, + } +} diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/SelectCaseButton.js b/nbri_ehr/resources/web/nbri_ehr/buttons/SelectCaseButton.js new file mode 100644 index 0000000..3477589 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/SelectCaseButton.js @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.form.field.SelectCaseButton', { + extend: 'Ext.button.Button', + alias: 'widget.nbri_ehr-selectcasebutton', + + text: 'Use Existing Case', + margin: '0 0 0 20', + animalId: null, + + handleCaseSelect: function(caseid, hideEdit){ + this.enableBubble('animalchange'); + + const store = this.getStore(caseid); + this.on('storeloaded', function(panel){ + + const rec = store.getAt(0); + EHR.DemographicsCache.reportCaseSelected(rec); + panel.fireEvent('animalchange', rec.data.Id); + + let editCases = this.up('#upperPanel')?.query('nbri_ehr-editCases')?.[0]; + editCases.fieldEnableChange(true); + if (hideEdit) + editCases.editBtn.hide(); + }); + }, + + onRender: function(){ + this.callParent(arguments); + + const caseid = LABKEY.ActionURL.getParameter('caseid'); + const edit = LABKEY.ActionURL.getParameter('edit'); + if (caseid){ + this.handleCaseSelect(caseid, !edit); + } + else { + const taskid = LABKEY.ActionURL.getParameter('taskId') || LABKEY.ActionURL.getParameter('taskid'); + if (taskid) { + let record = EHR.DataEntryUtils.getBoundRecord(this.up('panel')); + if (!record || !record.get('Id')) { + let tasksPanel = this.up('#upperPanel')?.query('ehr-formpanel')?.find(panel => panel.formConfig.name === 'tasks'); + let caseid = tasksPanel?.store?.data?.get(0)?.get('caseid'); + if (caseid) { + this.handleCaseSelect(caseid, false); + } + } + } + } + }, + + onAnimalChange: function(id){ + this.animalId = id; + }, + + handler: function(btn){ + if (this.animalId){ + var casepanel = this.up('panel').up('panel'); + Ext4.create('NBRI_EHR.window.SelectCaseWindow', {animalId: this.animalId, casepanel: casepanel}).show(); + } + else { + console.log('no id'); + } + }, + + getStore: function(caseid){ + if (this.store) + return this.store; + + this.store = Ext4.create('LABKEY.ext4.data.Store', { + schemaName: 'study', + queryName: 'Cases', + columns: 'lsid,objectid,caseid,taskid,Id,date,enddate,reviewdate,category,openRemark,closeRemark,performedby,plan,problemCategory,problemSubcategory', + filterArray: [ + LABKEY.Filter.create('objectid', caseid, LABKEY.Filter.Types.EQUAL), + ], + autoLoad: true, + listeners: { + scope: this, + load: function(store){ + //NOTE: consumed by SnapshotPanel + this.fireEvent('storeloaded', this); + }, + exception: function(store){ + //NOTE: refresh the store in order to avoid invalid data on the client + store.load(); + } + } + }); + + return this.store; + }, +}); diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/addClinicalObsButton.js b/nbri_ehr/resources/web/nbri_ehr/buttons/addClinicalObsButton.js new file mode 100644 index 0000000..ed854b4 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/addClinicalObsButton.js @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +EHR.DataEntryUtils.registerGridButton('NBRI_DAILY_CLINICAL_OBS', function(config){ + return Ext4.Object.merge({ + text: 'Daily Observations', + tooltip: 'Click to add daily observations', + handler: function(btn) { + LABKEY.Query.selectRows({ + schemaName: 'ehr', + queryName: 'observation_types', + ignoreFilter: true, + success: function (results) { + var grid = btn.up('gridpanel'); + if (results?.rows?.length > 0) { + for (var i = 0; i < results.rows.length; i++) { + var row = results.rows[i]; + if (row.value === 'Verified Id?' || row.value === 'Stool' || row.value === 'Activity' || + row.value === 'Appetite' || row.value === 'Hydration' || row.value === 'BCS') { + + var newRecord = grid.store.createModel({}); + newRecord.set({ + category: row.value, + }); + grid.store.add(newRecord); + } + } + } + else { + Ext4.Msg.alert('Unable to load observation types. Please contact the system administrator.'); + } + }, + failure: function (error) { + Ext4.Msg.alert('Unable to load observation types. Please contact the system administrator.'); + console.log('Error loading observation types: ' + error); + }, + scope: this + }); + } + }, config); +}); + +EHR.DataEntryUtils.registerGridButton('NBRI_DAILY_CLINICAL_OBS_ORDERS', function(config){ + return Ext4.Object.merge({ + text: 'Daily Observations', + tooltip: 'Click to add daily observation orders', + handler: function(btn) { + + LABKEY.Query.selectRows({ + schemaName: 'ehr', + queryName: 'observation_types', + ignoreFilter: true, + success: function (results) { + var grid = btn.up('gridpanel'); + if (results?.rows?.length > 0) { + for (var i = 0; i < results.rows.length; i++) { + var row = results.rows[i]; + if (row.value === 'Verified Id?' || row.value === 'Stool' || row.value === 'Activity' || + row.value === 'Appetite' || row.value === 'Hydration' || row.value === 'BCS') { + + var newRecord = grid.store.createModel({}); + newRecord.set({ + category: row.value, + frequency: 'SID' + }); + grid.store.add(newRecord); + } + } + } + else { + Ext4.Msg.alert('Unable to load observation types. Please contact the system administrator.'); + } + }, + failure: function (error) { + Ext4.Msg.alert('Unable to load observation types. Please contact the system administrator.'); + console.log('Error loading observation types: ' + error); + }, + scope: this + }); + } + }, config); +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/clinicalObsGridButton.js b/nbri_ehr/resources/web/nbri_ehr/buttons/clinicalObsGridButton.js new file mode 100644 index 0000000..be6c858 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/clinicalObsGridButton.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.DataEntryUtils.registerGridButton('NBRI_AUTO_POPULATE_DAILY_OBS', function(config){ + return Ext4.Object.merge({ + text: 'Auto Populate Clinical Obs', + xtype: 'button', + hidden: true, + listeners: { + render: function(btn){ + const id = LABKEY.ActionURL.getParameter('id'); + const caseid = LABKEY.ActionURL.getParameter('caseid'); + const scheduledDate = LABKEY.ActionURL.getParameter('scheduledDate'); + const scheduled = id && caseid && scheduledDate; + + LABKEY.Query.selectRows({ + schemaName: 'ehr', + queryName: 'observation_types', + ignoreFilter: true, + success: function (results) { + var grid = btn.up('gridpanel'); + if (grid?.store?.data?.getCount() === 0) { + if (results?.rows?.length > 0) { + for (var i = 0; i < results.rows.length; i++) { + var row = results.rows[i]; + if (row.value === 'Verified Id?' || row.value === 'Stool' || row.value === 'Activity' || + row.value === 'Appetite' || row.value === 'Hydration' || row.value === 'BCS') { + + var newRecord = grid.store.createModel({}); + newRecord.set({ + category: row.value, + }); + + if (scheduled) { + newRecord.set('Id', id); + newRecord.set('caseid', caseid); + newRecord.set('scheduledDate', scheduledDate); + } + grid.store.add(newRecord); + } + } + + if (scheduled) { + this.addEvents('animalchange'); + this.enableBubble('animalchange'); + this.fireEvent('animalchange', id); + grid.fireEvent('panelDataChange'); + } + } + } + }, + scope: this + }); + } + } + }, config); +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/deathNecropsyButtons.js b/nbri_ehr/resources/web/nbri_ehr/buttons/deathNecropsyButtons.js new file mode 100644 index 0000000..efee481 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/deathNecropsyButtons.js @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +/** + * Buttons specific to the Death-Necropsy form + */ + +EHR.DataEntryUtils.registerDataEntryFormButton('DEATHSUBMIT', { + text: 'Submit Death', + name: 'submitDeath', + errorThreshold: 'ERROR', + successURL: LABKEY.ActionURL.buildURL('ehr', 'enterData.view'), + itemId: 'submitDeathBtn', + disabled: true, + requiredQC: 'Request: Pending', + targetQC: 'Request: Pending', + handler: function(submitDeathBtn){ + Ext4.Msg.confirm('Confirm', 'You are about to submit a death record (any necropsy info entered will be discarded during this step). This will send an email notification to the appropriate parties to enter Necropsy. Submit death?', function(val){ + if (val == 'yes') { + var panel = submitDeathBtn.up('ehr-dataentrypanel'); + panel.storeCollection.clientStores.each((store) => { + if (store.storeId && (store.storeId.indexOf('necropsy') > -1) || store.storeId.indexOf('grossPathology') > -1 || store.storeId.indexOf('tissueDisposition') > -1) { + store.removeAll(); + } + }); + + // get and set 'Veterinarians' as the assignedTo value + var assignedToCombo = panel.down('ehr-usersandgroupscombo'); + if (assignedToCombo) { + var assignedToStore = assignedToCombo.getStore(); + if (assignedToStore.count() > 0) { + var assignedToRec = assignedToStore.findRecord('DisplayName', 'Veterinarians'); + if (assignedToRec) { + var taskStore = panel.storeCollection.getServerStoreForQuery('ehr', 'tasks'); + taskStore.getAt(0).set('assignedto', assignedToRec.get('UserId')); + panel.storeCollection.transformServerToClient(); + } + } + } + + panel.onSubmit(submitDeathBtn); + } + }, this); + }, + disableOn: 'ERROR' +}); + +EHR.DataEntryUtils.registerDataEntryFormButton('DEATH_NECROPSY_VET_REVIEW', { + text: 'Submit Necropsy for Review', + name: 'review', + requiredQC: 'Review Required', + targetQC: 'Review Required', + errorThreshold: 'WARN', + successURL: LABKEY.ActionURL.getParameter('returnUrl') || LABKEY.ActionURL.buildURL('ehr', 'enterData.view'), + disabled: true, + itemId: 'reviewBtn', + disableOn: 'ERROR', + handler: function(btn){ + var panel = btn.up('ehr-dataentrypanel'); + + Ext4.create('NBRI_EHR.window.DeathNecropsySubmitForReviewWindow', { + dataEntryPanel: panel, + dataEntryBtn: btn, + reviewRequiredRecipient: panel.formConfig.defaultReviewRequiredPrincipal + }).show(); + + } +}); + +Ext4.define('NBRI_EHR.window.DeathNecropsySubmitForReviewWindow', { + extend: 'Ext.window.Window', + + initComponent: function(){ + Ext4.apply(this, { + closeAction: 'destroy', + modal: true, + title: 'Submit For Review', + width: 430, + buttons: [{ + text:'Submit', + disabled:false, + itemId: 'submit', + scope: this, + handler: function(btn){ + var win = btn.up('window'); + var assignedTo = win.down('#assignedTo').getValue(); + if(!assignedTo){ + alert('Must assign this task to someone'); + return; + } + + var taskStore = this.dataEntryPanel.storeCollection.getServerStoreForQuery('ehr', 'tasks'); + taskStore.getAt(0).set('assignedto', assignedTo); + this.dataEntryPanel.storeCollection.transformServerToClient(); + this.dataEntryPanel.onSubmit(this.dataEntryBtn); + win.close(); + } + },{ + text: 'Cancel', + scope: this, + handler: function(btn){ + btn.up('window').hide(); + } + }], + items: [{ + bodyStyle: 'padding:5px;', + items: [{ + html: this.reviewRecipientMsg || '', + border: false, + style: 'padding-bottom: 10px;', + hidden: !this.reviewRecipientMsg + },{ + xtype: 'labkey-combo', + forceSelection: true, + fieldLabel: 'Assign To', + width: 400, + queryMode: 'local', + store: { + type: 'labkey-store', + schemaName: 'ehr_lookups', + queryName: 'veterinarians', + columns: 'UserId, DisplayName', + autoLoad: true + }, + value: this.getDefaultRecipient(), + displayField: 'DisplayName', + valueField: 'UserId', + itemId: 'assignedTo', + id: 'assignedTo', + anyMatch: true, + caseSensitive: false, + }] + }] + }); + + this.callParent(arguments); + }, + + getDefaultRecipient: function(){ + return this.reviewRequiredRecipient; + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/necropsyGridButtons.js b/nbri_ehr/resources/web/nbri_ehr/buttons/necropsyGridButtons.js new file mode 100644 index 0000000..50fc9b6 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/necropsyGridButtons.js @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.DataEntryUtils.registerGridButton('ADDGROSSPATHOLOGY', function(config){ + return Ext4.Object.merge({ + text: 'Add', + xtype: 'button', + hidden: true, + listeners: { + render: function(btn){ + LABKEY.Query.selectRows({ + schemaName: 'ehr_lookups', + queryName: 'necropsy_organ_systems', + ignoreFilter: true, + success: function (results) { + var grid = btn.up('gridpanel'); + if (grid && grid.store && grid.store.data && grid.store.data.getCount() === 0) { + if (results && results.rows && results.rows.length > 0) { + for (var i = 0; i < results.rows.length; i++) { + var row = results.rows[i]; + var newRecord = grid.store.createModel({}); + newRecord.set({ + systemExamined: row.title, + }); + grid.store.add(newRecord); + } + } + } + }, + scope: this + }); + } + } + }, config); +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/saveDraftButton.js b/nbri_ehr/resources/web/nbri_ehr/buttons/saveDraftButton.js new file mode 100644 index 0000000..6fac4ab --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/saveDraftButton.js @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.DataEntryUtils.registerDataEntryFormButton('NBRISAVEDRAFTBUTTON', { + text: 'Save Draft', + name: 'nbriSaveDraft', + errorThreshold: 'ERROR', + successURL: LABKEY.ActionURL.buildURL('ehr', 'enterData.view'), + itemId: 'nbriSaveDraftBtn', + disabled: false, + requiredQC: 'In Progress', + targetQC: 'In Progress', + handler: function(btn){ + var panel = btn.up('ehr-dataentrypanel'); + panel.onSubmit(btn, false, true); + }, + disableOn: 'ERROR' +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/buttons/treatmentSubmit.js b/nbri_ehr/resources/web/nbri_ehr/buttons/treatmentSubmit.js new file mode 100644 index 0000000..2134059 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/buttons/treatmentSubmit.js @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +EHR.DataEntryUtils.registerDataEntryFormButton('NBRI_TREATMENT_SUBMIT', { + text: 'Submit Final', + name: 'submit', + requiredQC: 'Completed', + targetQC: 'Completed', + errorThreshold: 'INFO', + successURL: LABKEY.ActionURL.getParameter('returnUrl') || LABKEY.ActionURL.buildURL('ehr', 'enterData.view'), + disabled: true, + itemId: 'submitBtn', + handler: function(btn){ + + const panel = btn.up('ehr-dataentrypanel'); + const casesStore = panel?.storeCollection?.getClientStoreByName('cases'); + if (casesStore) { + const rec = casesStore.getAt(0); + const caseid = casesStore.getAt(0).get('caseid'); + const qcstate = casesStore.getAt(0).get('qcstate/label'); + if (!caseid || (qcstate && qcstate !== 'Completed')) { // only check for new cases or cases going from some other state to Completed + const id = rec.get('Id'); + const problemCategory = rec.get('problemCategory'); + const category = rec.get('category'); + if (id && problemCategory && category) { + const filters = [ + LABKEY.Filter.create('Id', id), + LABKEY.Filter.create('category', category), + LABKEY.Filter.create('problemCategory', problemCategory), + LABKEY.Filter.create('isActive', true), + LABKEY.Filter.create('QCState/Label', "Completed", LABKEY.Filter.Types.EQUAL) + ] + const caseid = rec.get('caseid'); + if (caseid) { + filters.push(LABKEY.Filter.create('caseid', caseid, LABKEY.Filter.Types.NEQ)) + } + LABKEY.Query.selectRows({ + schemaName: 'study', + queryName: 'cases', + filterArray: filters, + columns: 'problemSubcategory', + scope: this, + ignoreFilter: true, + failure: LDK.Utils.getErrorCallback(), + success: function (results) { + if (results.rows.length > 0) { + const subcategories = []; + for (let i = 0; i < results.rows.length; i++) { + subcategories.push(results.rows[i].problemSubcategory); + } + let msg; + if (subcategories.length === 1) { + msg = 'This animal already has a case with the problem ' + problemCategory + '. The subcategory is ' + results.rows[0].problemSubcategory + '. Do you still want to submit this case?'; + } + else { + msg = 'This animal already has ' + subcategories.length + ' cases with the problem ' + problemCategory + '. The subcategories are ' + subcategories.join(', ') + '. Do you still want to submit this case?'; + } + + Ext4.Msg.confirm('Similar Case Exists', msg, function (v) { + if (v == 'yes') + this.onSubmit(btn); + }, this); + } + else { + Ext4.Msg.confirm('Finalize Form', 'You are about to finalize this form. Do you want to do this?', function (v) { + if (v == 'yes') + this.onSubmit(btn); + }, this); + } + } + }); + } + else { + Ext4.Msg.confirm('Finalize Form', 'You are about to finalize this form. Do you want to do this?', function (v) { + if (v == 'yes') + this.onSubmit(btn); + }, this); + } + } + else { + Ext4.Msg.confirm('Finalize Form', 'You are about to finalize this form. Do you want to do this?', function (v) { + if (v == 'yes') + this.onSubmit(btn); + }, this); + } + } + else { + Ext4.Msg.confirm('Finalize Form', 'You are about to finalize this form. Do you want to do this?', function (v) { + if (v == 'yes') + this.onSubmit(btn); + }, this); + } + }, + listeners: { + afterRender: function(btn){ + const treatmentid = LABKEY.ActionURL.getParameter('treatmentid'); + const scheduledDate = LABKEY.ActionURL.getParameter('scheduledDate'); + const obsTask = LABKEY.ActionURL.getParameter('obsTask'); + const id = LABKEY.ActionURL.getParameter('id'); + const observations = LABKEY.ActionURL.getParameter('observations'); + const prcOrderId = LABKEY.ActionURL.getParameter('prcOrderId'); + + if (treatmentid) { + + this.addEvents('animalchange'); + this.enableBubble('animalchange'); + + function onSuccess(results) { + if (results.rows.length === 0) { + console.error('No treatment order found for treatmentid ' + treatmentid); + return; + } + + const drugGrid = this.up('ehr-dataentrypanel').query('grid').find(e => e.title === "Medications/Treatments Given"); + if (!drugGrid) { + console.error('Medication/Treatments grid not found'); + return; + } + + const row = results.rows[0]; + const record = { + Id: row.Id?.value, + category: row.category?.value, + code: row.code?.value, + route: row.route?.value, + concentration: row.concentration?.value, + conc_units: row.conc_units?.value, + amount: row.amount?.value, + amount_units: row.amount_units?.value, + dosage: row.dosage?.value, + dosage_units: row.dosage_units?.value, + volume: row.volume?.value, + vol_units: row.vol_units?.value, + orderedby: row.orderedby?.value, + treatmentid: row.objectid?.value, + caseid: row.caseid?.value + }; + + if (scheduledDate) { + record.scheduledDate = scheduledDate; + } + + drugGrid.store.add(record); + + this.fireEvent('animalchange', row.Id?.value); + drugGrid.fireEvent('panelDataChange'); + } + + LABKEY.Query.selectRows({ + requiredVersion: 9.1, + schemaName: 'study', + queryName: 'treatment_order', + columns: 'Id,meaning,code,qualifier,route,concentration,conc_units,amount,amount_units,dosage,dosage_units,volume,vol_units,remark,category,objectid,orderedby', + filterArray: [LABKEY.Filter.create('objectid', treatmentid, LABKEY.Filter.Types.EQUAL)], + scope: this, + ignoreFilter: true, + success: onSuccess, + failure: LDK.Utils.getErrorCallback() + }); + + } + + if (id && observations) { + this.addEvents('animalchange'); + this.enableBubble('animalchange'); + + function onObsSuccess(results) { + if (results.rows.length === 0) { + console.error('No observations found for taskid ' + obsTask + ' and id ' + id); + return; + } + + const obsGrid = this.up('ehr-dataentrypanel').query('grid').find(e => e.title === "Observations"); + if (!obsGrid) { + console.error('Observations grid not found'); + return; + } + + const categories = []; + for (let i = 0; i < results.rows.length; i++) { + let row = results.rows[i]; + + if (!categories.includes(row.category.value)) { + let record = { + Id: row.Id?.value, + category: row.category?.value, + area: row.area?.value, + orderId: row.objectid?.value, + caseid: row.caseid?.value + }; + + if (scheduledDate) { + record.scheduledDate = scheduledDate; + } + + obsGrid.store.add(record); + categories.push(row.category?.value); + } + } + + this.fireEvent('animalchange', results.rows[0].Id.value); + obsGrid.fireEvent('panelDataChange'); + } + + LABKEY.Query.selectRows({ + requiredVersion: 9.1, + schemaName: 'study', + queryName: 'observation_order', + columns: 'Id,category,area,objectid,caseid', + filterArray: [LABKEY.Filter.create('taskid', obsTask, LABKEY.Filter.Types.EQUALS_ONE_OF), + LABKEY.Filter.create('id', id, LABKEY.Filter.Types.EQUAL), + LABKEY.Filter.create('category', observations, LABKEY.Filter.Types.EQUALS_ONE_OF)], + scope: this, + ignoreFilter: true, + success: onObsSuccess, + failure: LDK.Utils.getErrorCallback() + }); + } + + if (prcOrderId) { + + this.addEvents('animalchange'); + this.enableBubble('animalchange'); + + function onSuccess(results) { + if (results.rows.length === 0) { + console.error('No procedure order found for procedure id ' + prcOrderId); + return; + } + + const prcGrid = this.up('ehr-dataentrypanel').query('grid').find(e => e.title === "Procedures"); + if (!prcGrid) { + console.error('Procedures grid not found'); + return; + } + + const row = results.rows[0]; + const record = { + Id: row.Id?.value, + category: row.category?.value, + procedure: row.procedure?.value, + caseid: row.caseid?.value, + orderedby: row.orderedby?.value, + orderid: row.objectid?.value + }; + + prcGrid.store.add(record); + + this.fireEvent('animalchange', row.Id.value); + prcGrid.fireEvent('panelDataChange'); + } + + LABKEY.Query.selectRows({ + requiredVersion: 9.1, + schemaName: 'study', + queryName: 'prc_order', + columns: 'Id,procedure,remark,category,objectid,orderedby,caseid', + filterArray: [LABKEY.Filter.create('objectid', prcOrderId, LABKEY.Filter.Types.EQUAL)], + ignoreFilter: true, + scope: this, + success: onSuccess, + failure: LDK.Utils.getErrorCallback() + }); + + } + + } + }, + disableOn: 'WARN' +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/data/AssignmentsAnyIdClientStore.js b/nbri_ehr/resources/web/nbri_ehr/data/AssignmentsAnyIdClientStore.js new file mode 100644 index 0000000..f6f6e62 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/AssignmentsAnyIdClientStore.js @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.data.AssignmentsAnyIdClientStore', { + extend: 'NBRI_EHR.data.AssignmentsClientStore', + + getExtraContext: function () { + var ret = this.callParent(arguments) || {}; + + // Tell the trigger scripts to allow any Id. Requires handling in trigger script to fully enable. + ret['allowAnyId'] = true; + return ret; + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/data/AssignmentsClientStore.js b/nbri_ehr/resources/web/nbri_ehr/data/AssignmentsClientStore.js new file mode 100644 index 0000000..bdd28b5 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/AssignmentsClientStore.js @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +/** + * @param fieldConfigs + */ +Ext4.define('NBRI_EHR.data.AssignmentsClientStore', { + extend: 'EHR.data.DataEntryClientStore', + + getExtraContext: function(){ + var rows = []; + var allRecords = this.getRange(); + for (var idx = 0; idx < allRecords.length; ++idx){ + var record = allRecords[idx]; + + var date = record.get('date'); + var id = record.get('Id'); + var protocol = record.get('protocol'); + var project = record.get('project'); + if (!id || !date || !protocol || !project) + continue; + + date = Ext4.Date.format(date, LABKEY.extDefaultDateFormat); + + if (protocol) { + rows.push({ + Id: id, + objectid: record.get('objectid'), + date: date, + enddate: record.get('enddate'), + qcstate: record.get('QCState'), + protocol: record.get('protocol') + }); + } + else if (project) { + rows.push({ + Id: id, + objectid: record.get('objectid'), + date: date, + enddate: record.get('enddate'), + qcstate: record.get('QCState'), + project: record.get('project') + }); + } + + } + + if (!Ext4.isEmpty(rows)){ + rows = Ext4.encode(rows); + + return { + assignmentsInTransaction: rows + } + } + + return null; + } +}); diff --git a/nbri_ehr/resources/web/nbri_ehr/data/CaseClientStore.js b/nbri_ehr/resources/web/nbri_ehr/data/CaseClientStore.js new file mode 100644 index 0000000..6a1cbc0 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/CaseClientStore.js @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +Ext4.define('NBRI_EHR.data.CaseClientStore', { + extend: 'EHR.data.ParentClientStore', + + getExtraContext: function(){ + // Pass through cases for validation in clinremarks + var caseMap = {}; + var allRecords = this.getRange(); + for (var idx = 0; idx < allRecords.length; ++idx){ + var record = allRecords[idx]; + if (record.get('objectid')){ + var id = record.get('Id'); + var date = record.get('date'); + if (!id || !date) + continue; + + date = Ext4.Date.format(date, LABKEY.extDefaultDateFormat); + + if (!caseMap[id]) + caseMap[id] = []; + + caseMap[id].push({ + objectid: record.get('objectid'), + date: date, + qcstate: record.get('QCState'), + caseid: record.get('caseid'), + enddate: record.get('enddate') + }); + } + } + + if (!LABKEY.Utils.isEmptyObj(caseMap)){ + caseMap = Ext4.encode(caseMap); + + return { + casesInTransaction: caseMap + } + } + + return null; + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/data/CaseStoreCollection.js b/nbri_ehr/resources/web/nbri_ehr/data/CaseStoreCollection.js new file mode 100644 index 0000000..4e0f662 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/CaseStoreCollection.js @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.data.CaseStoreCollection', { + extend: 'EHR.data.StoreCollection', + + constructor: function(){ + this.callParent(arguments); + + this.mon(EHR.DemographicsCache, 'caseselected', this.onCaseSelected, this); + this.mon(EHR.DemographicsCache, 'casecreated', this.onCaseCreated, this); + }, + + onCaseCreated: function(){ + var record = this.getClientCaseRec(); + if (record){ + // iterate through record properties and set them to null + Ext4.Object.each(record.data, function(key, value){ + if(key !== 'Id' && key !== 'category') + record.set(key, null); + }); + + } + + record = this.getServerCaseRec(); + if (record){ + // iterate through record properties and set them on the case record + Ext4.Object.each(record.data, function(key, value){ + if(key !== 'Id' && key !== 'category') + record.set(key, null); + }); + + } + }, + + onCaseSelected: function(record){ + var rec = this.getClientCaseRec(); + if (rec && record){ + // iterate through record properties and set them on the case record + Ext4.Object.each(record.data, function(key, value){ + if (rec.fields.keys.indexOf(key) !== -1) + rec.set(key, value); + }); + + // Required to not try to insert a new case. Indicates if a record is not saved in the db. This one is already saved. + rec.phantom = false; + } + + rec = this.getServerCaseRec(); + if (rec && record){ + // iterate through record properties and set them on the case record + Ext4.Object.each(record.data, function(key, value){ + if (rec.fields.keys.indexOf(key) !== -1) + rec.set(key, value); + }); + + // Required to not try to insert a new case. Indicates if a record is not saved in the db. This one is already saved. + rec.phantom = false; + } + + this.validateAll(); + }, + + getClientCaseStore: function(){ + if (this.clientCaseStore){ + return this.clientCaseStore; + } + + this.clientCaseStore = this.getClientStoreByName('cases'); + LDK.Assert.assertNotEmpty('Unable to find cases store in CaseStoreCollection', this.clientCaseStore); + + return this.clientCaseStore; + }, + + getClientCaseRec: function(){ + var caseStore = this.getClientCaseStore(); + if (caseStore){ + LDK.Assert.assertTrue('More than 1 record found in Cases store, actual: ' + caseStore.getCount(), caseStore.getCount() <= 1); + if (caseStore.getCount() == 1){ + return caseStore.getAt(0); + } + } + }, + + getServerCaseStore: function(){ + if (this.serverCaseStore){ + return this.serverCaseStore; + } + + this.serverCaseStore = this.getServerStoreByName('study.cases'); + LDK.Assert.assertNotEmpty('Unable to find cases store in CaseStoreCollection', this.serverCaseStore); + + return this.serverCaseStore; + }, + + getServerCaseRec: function(){ + var caseStore = this.getServerCaseStore(); + if (caseStore){ + LDK.Assert.assertTrue('More than 1 record found in Cases store, actual: ' + caseStore.getCount(), caseStore.getCount() <= 1); + if (caseStore.getCount() == 1){ + return caseStore.getAt(0); + } + } + }, + + getDefaultValues: function(){ + var rec = this.getClientCaseRec(); + if (rec){ + return { + Id: rec.get('Id'), + caseid: rec.get('objectid') + } + } + + return null; + }, + + onClientStoreUpdate: function(){ + this.doUpdateRecords(); + this.callParent(arguments); + }, + + doUpdateRecords: function(){ + var newValues = this.getDefaultValues() || {}; + var cacheKey = newValues ? (newValues.Id + '||' + newValues.caseid) : null; + + if (cacheKey !== this._cachedKey){ + var caseStore = this.getClientCaseStore(); + this.clientStores.each(function(cs){ + if (cs.storeId == caseStore.storeId){ + return; + } + + var toSet = {}; + + if (cs.getFields().get('Id') != null){ + toSet.Id = newValues.Id; + } + if (cs.getFields().get('caseid') != null){ + toSet.caseid = newValues.caseid; + } + + if (Ext4.Object.isEmpty(toSet)){ + return; + } + + var storeChanged = false; + cs.suspendEvents(); + cs.each(function(rec){ + var needsUpdate = false; + for (var field in toSet){ + if (toSet[field] !== rec.get(field)){ + needsUpdate = true; + } + } + + if (needsUpdate){ + storeChanged = true; + rec.set(toSet); + } + }, this); + cs.resumeEvents(); + + if (storeChanged) + cs.fireEvent('datachanged', cs); + }, this); + } + // Only validate once stores have loaded, otherwise can have perf issues when loading existing cases + else if( this.haveStoresLoaded ) { + // Validate across the sections, such as clin_remark not required if case close date entered + this.validateAll(); + } + + this._cachedKey = cacheKey; + }, + + getTaskId: function(){ + if (this.taskId) { + return this.taskId; + } + + var model = this.getServerStoreForQuery('ehr', 'tasks').getAt(0); + if (model){ + return model.get('taskid'); + } + + console.error('Unable to find taskid'); + return null + }, + + setClientModelDefaults: function(model){ + if (!model.get('taskid')){ + model.suspendEvents(); + model.set('taskid', this.getTaskId()); + model.resumeEvents(); + } + + return this.callParent([model]); + }, + + commitChanges: function(){ + // ensure all records are using this taskId and alert if not + var taskid = this.getTaskId(); + if (taskid){ + this.clientStores.each(function(cs){ + if (cs.getFields().get('taskid') != null && cs.storeId !== this.collectionId + '-cases'){ + cs.each(function(r){ + if (taskid != r.get('taskid')){ + LDK.Assert.assertEquality('Incorrect taskid for client store:' + cs.storeId, taskid, r.get('taskid')); + r.beginEdit(); + r.set('taskid', this.getTaskId()); + r.endEdit(true); + } + }, this); + } + }, this); + + this.serverStores.each(function(cs){ + if (cs.getFields().get('taskid') != null && cs.storeId.indexOf('|cases|') === -1){ + cs.each(function(r){ + if (r.isRemovedRequest){ + return; //do not check these records. they have deliberately been separated. + } + + if (taskid != r.get('taskid')){ + LDK.Assert.assertEquality('Incorrect taskid for server store:' + cs.storeId, taskid, r.get('taskid')); + r.beginEdit(); + r.set('taskid', this.getTaskId()); + r.endEdit(true); + } + }, this); + } + }, this); + } + + return this.callParent(arguments); + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/data/ClinicalObservationClientStore.js b/nbri_ehr/resources/web/nbri_ehr/data/ClinicalObservationClientStore.js new file mode 100644 index 0000000..6c51e1d --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/ClinicalObservationClientStore.js @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.data.ClinicalObservationsClientStore', { + extend: 'EHR.data.DataEntryClientStore', + + constructor: function(){ + this.callParent(arguments); + + this.observationTypesStore = EHR.DataEntryUtils.getObservationTypesStore(); + }, + + getExtraContext: function(){ + // Pass through tasks for entering observations from schedule + const obsTask = LABKEY.ActionURL.getParameter('obsTask'); + + return { + orderTasksInTransaction: [obsTask] + + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/data/DrugAdministrationRunsChildClientStore.js b/nbri_ehr/resources/web/nbri_ehr/data/DrugAdministrationRunsChildClientStore.js new file mode 100644 index 0000000..03e48ce --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/DrugAdministrationRunsChildClientStore.js @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +Ext4.define('NBRI_EHR.data.DrugAdministrationRunsChildClientStore', { + extend: 'NBRI_EHR.data.DrugAdministrationRunsClientStore', + + insert: function(index, records) { + var ret = this.callParent(arguments); + + // after insert of a new, track down the parent record to get the fields to inherit + if (this.sectionCfg && this.sectionCfg.extraProperties && this.sectionCfg.extraProperties.parentQueryName) { + var parentQuery = this.sectionCfg.extraProperties.parentQueryName; + var parentStore = this.storeCollection.getClientStoreByName(parentQuery); + var parentRecord = parentStore ? parentStore.getAt(0) : null; + if (parentRecord && Ext4.isFunction(parentStore.onRecordUpdate)) { + // get the set of inherited field names + var inheritFieldNames = []; + Ext4.each(this.getFields().items, function(field) { + if (field.inheritFromParent) { + inheritFieldNames.push(field.name); + } + }); + + parentStore.onRecordUpdate(parentRecord, inheritFieldNames); + } + } + + return ret; + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/data/DrugAdministrationRunsClientStore.js b/nbri_ehr/resources/web/nbri_ehr/data/DrugAdministrationRunsClientStore.js new file mode 100644 index 0000000..5aa1835 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/DrugAdministrationRunsClientStore.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.data.DrugAdministrationRunsClientStore', { + extend: 'EHR.data.DrugAdministrationRunsClientStore', + + // This override adds a special case for frequency to align formulary frequency.rowid with data frequency.meaning + onRecordUpdate: function (record, modifiedFieldNames) { + if (record.get('code')) { + modifiedFieldNames = modifiedFieldNames || []; + + if (modifiedFieldNames.indexOf('code') == -1) { + return; + } + + if (!this.formularyStore) { + LDK.Utils.logToServer({ + message: 'Unable to find formulary store in DrugAdministrationRunsClientStore' + }); + console.error('Unable to find formulary store in DrugAdministrationRunsClientStore'); + + return; + } + + var values = this.formularyStore.getFormularyValues(record.get('code')); + if (!Ext4.Object.isEmpty(values)) { + var params = {}; + + for (var fieldName in this.fieldMap) { + if (!this.getFields().get(fieldName)) { + continue; + } + + if (modifiedFieldNames.indexOf(this.fieldMap[fieldName]) != -1) { + continue; + } + + let def = values[fieldName]; + + // Special case for frequency to align the formulary frequency rowid with data stored as the meaning + if (fieldName.toLowerCase() === 'frequency') + def = values['frequency/meaning'] + + if (Ext4.isDefined(def)) { + params[this.fieldMap[fieldName]] = def; + } + } + + if (!LABKEY.Utils.isEmptyObj(params)) { + record.beginEdit(); + record.set(params); + record.endEdit(true); + } + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/data/ObsOrderChildClientStore.js b/nbri_ehr/resources/web/nbri_ehr/data/ObsOrderChildClientStore.js new file mode 100644 index 0000000..f5e0d22 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/ObsOrderChildClientStore.js @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.data.ObsOrderChildClientStore', { + extend: 'NBRI_EHR.data.ObsOrdersClientStore', + + insert: function(index, records) { + var ret = this.callParent(arguments); + + // after insert of a new, track down the parent record to get the fields to inherit + if (this.sectionCfg && this.sectionCfg.extraProperties && this.sectionCfg.extraProperties.parentQueryName) { + var parentQuery = this.sectionCfg.extraProperties.parentQueryName; + var parentStore = this.storeCollection.getClientStoreByName(parentQuery); + var parentRecord = parentStore ? parentStore.getAt(0) : null; + if (parentRecord && Ext4.isFunction(parentStore.onRecordUpdate)) { + // get the set of inherited field names + var inheritFieldNames = []; + Ext4.each(this.getFields().items, function(field) { + if (field.inheritFromParent) { + inheritFieldNames.push(field.name); + } + }); + + parentStore.onRecordUpdate(parentRecord, inheritFieldNames); + } + } + + return ret; + } + +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/data/ObsOrdersClientStore.js b/nbri_ehr/resources/web/nbri_ehr/data/ObsOrdersClientStore.js new file mode 100644 index 0000000..b10fdf9 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/ObsOrdersClientStore.js @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.data.ObsOrdersClientStore', { + extend: 'EHR.data.DataEntryClientStore', + + constructor: function(){ + this.callParent(arguments); + + this.observationTypesStore = EHR.DataEntryUtils.getObservationTypesStore(); + }, + + getExtraContext: function(){ + // Pass through cases for validation in clinremarks + var orders = []; + var allRecords = this.getRange(); + for (var idx = 0; idx < allRecords.length; ++idx){ + var record = allRecords[idx]; + if (record.get('category')){ + var id = record.get('Id'); + var date = record.get('date'); + if (!id || !date) + continue; + + date = Ext4.Date.format(date, LABKEY.extDefaultDateFormat); + + orders.push({ + id: id, + objectid: record.get('objectid'), + date: date, + qcstate: record.get('QCState'), + taskid: record.get('taskid'), + category: record.get('category'), + frequency: record.get('frequency') + }); + } + } + + return { + ordersInTransaction: orders + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/field/AnimalIdCases.js b/nbri_ehr/resources/web/nbri_ehr/field/AnimalIdCases.js new file mode 100644 index 0000000..dee8322 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/field/AnimalIdCases.js @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.form.AnimalIdCases', { + extend: 'Ext.panel.Panel', + alias: 'widget.nbri_ehr-animalIdCases', + layout: { + type: 'hbox', + }, + + initComponent: function(){ + this.on('resize', function(){ + this.setWidth(700); + }); + + this.idField = Ext4.create('EHR.form.AnimalIdUpperField', { + id: 'animal_id', + name: 'Id', + width: 245 + }); + + this.existingCasesBtn = Ext4.create('NBRI_EHR.form.field.SelectCaseButton', { + id: 'existing_cases', + }); + + this.label = Ext4.create('Ext.form.Label', { + text: 'Id:', + forId: 'animal_id', + margin: '0 138 0 0', + cls: 'black-text-color' + }); + + this.items = [ + this.label, + this.idField, + this.existingCasesBtn + ] + + this.existingCasesBtn.disable(); + + if (this.idField){ + this.mon(this.idField, 'animalchange', this.onAnimalChange, this, {buffer: 1000}); + } + + this.callParent(); + }, + + onAnimalChange: function(){ + this.existingCasesBtn.onAnimalChange(this.idField.getValue()); + this.existingCasesBtn.enable(); + }, + + setValue: function(value){ + this.idField.setValue(value); + }, + + disable: function(){ + this.idField.disable(); + this.label.addCls('form-panel-input-disabled'); + this.idField.inputEl.addCls('form-panel-input-disabled'); + + }, + + enable: function(){ + this.idField.enable(); + this.label.removeCls('form-panel-input-disabled'); + this.idField.inputEl.removeCls('form-panel-input-disabled'); + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/field/DrugVolumeField.js b/nbri_ehr/resources/web/nbri_ehr/field/DrugVolumeField.js new file mode 100644 index 0000000..7976199 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/field/DrugVolumeField.js @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +Ext4.define('NBRI_EHR.field.DrugVolumeField', { + extend: 'EHR.form.field.DrugVolumeField', + alias: 'widget.nbri_ehr-drugvolumefield', + + triggerCls: 'x4-form-search-trigger', + triggerToolTip: 'Click to calculate amount based on concentration and volume', + + initComponent: function(){ + this.callParent(arguments); + this.getSnomedStore(); + }, + + getSnomedStore: function(){ + if (NBRI_EHR._snomedStore) + return NBRI_EHR._snomedStore; + + var storeId = ['ehr_lookups', 'snomed', 'code', 'meaning'].join('||'); + + NBRI_EHR._snomedStore = Ext4.create('LABKEY.ext4.data.Store', { + type: 'labkey-store', + schemaName: 'ehr_lookups', + queryName: 'snomed', + columns: 'code,meaning', + sort: 'meaning', + storeId: storeId, + autoLoad: true, + getRecordForCode: function(code){ + var recIdx = this.findExact('code', code); + if (recIdx != -1){ + return this.getAt(recIdx); + } + } + }); + + return NBRI_EHR._snomedStore; + }, + + onTriggerClick: function(){ + var record = EHR.DataEntryUtils.getBoundRecord(this); + if (!record){ + return; + } + + if (!record.get('code') || !record.get('Id')){ + Ext4.Msg.alert('Error', 'Must enter the Animal Id and treatment'); + return; + } + + Ext4.create('NBRI_EHR.window.DrugAmountWindow', { + targetStore: record.store, + formConfig: record.sectionCfg, + boundRecord: record + }).show(); + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/field/EditCase.js b/nbri_ehr/resources/web/nbri_ehr/field/EditCase.js new file mode 100644 index 0000000..9b240a5 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/field/EditCase.js @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.form.EditCases', { + extend: 'Ext.panel.Panel', + alias: 'widget.nbri_ehr-editCases', + layout: { + type: 'hbox', + }, + editing: false, + disabled: false, + readonly: false, + + initComponent: function(){ + this.on('resize', function () { + this.setWidth(700); + }); + + let caseid = LABKEY.ActionURL.getParameter('caseid'); + let taskid = LABKEY.ActionURL.getParameter('taskId'); + + this.editBtn = Ext4.create('Ext.button.Button', { + text: 'Edit', + margin: '20 10 0 0', + hidden: !caseid && !taskid, + scope: this, + handler: this.onEditButtonClick + }); + + this.items = [ + this.editBtn, + ] + + this.mon(EHR.DemographicsCache, 'caseselected', this.onCaseSelect, this); + + this.callParent(); + }, + + disableItem(item, disable) { + if (disable) { + item.disable(); + } + else { + item.enable(); + } + }, + + disabledDisplay: function(item, disable){ + if (item.labelEl && item.inputEl) { + if (disable) { + item.labelEl.addCls('form-panel-input-disabled'); + item.inputEl.addCls('form-panel-input-disabled'); + } + else { + item.labelEl.removeCls('form-panel-input-disabled'); + item.inputEl.removeCls('form-panel-input-disabled'); + } + } + + if (item.labelEl && item.containerEl) { + if (disable) { + item.labelEl.addCls('form-panel-input-disabled'); + item.containerEl.addCls('form-panel-input-disabled'); + } + else { + item.labelEl.removeCls('form-panel-input-disabled'); + item.containerEl.removeCls('form-panel-input-disabled'); + } + } + }, + + fieldEnableChange: function(disable){ + var panel = this.up('panel'); + panel.items.each(function(item){ + if (item.name != 'objectid'){ + this.disableItem(item, disable); + this.disabledDisplay(item, disable); + } + }, this); + }, + + onEditButtonClick: function(){ + if (this.disabled) { + this.disabled = false; + this.fieldEnableChange(false); + } + else { + this.disabled = true; + this.fieldEnableChange(true); + } + }, + + onCaseSelect: function(){ + this.fieldEnableChange(true); + if (this.readonly) { + return; + } + this.editing = true; + this.disabled = true; + this.editBtn.show(); + }, + + onNewCase: function(){ + EHR.DemographicsCache.reportCaseCreated(); + this.editing = false; + this.editBtn.hide(); + this.fieldEnableChange(false); + }, + + disable: function(){}, + + enable: function(){} +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/field/LocationField.js b/nbri_ehr/resources/web/nbri_ehr/field/LocationField.js new file mode 100644 index 0000000..20d4b2b --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/field/LocationField.js @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + * + * @cfg pairedWithRoomField. Note: if true, you must implement getRoomField(), which returns the cognate ehr-roomfield + */ +Ext4.define('NBRI_EHR.field.LocationField', { + extend: 'Ext.ux.CheckCombo', + alias: 'widget.nbri_ehr-locationField', + + fieldLabel: 'Location', + nullCaption: '[Blank]', + editable: true, + expandToFitContent: true, + addAllSelector: true, + typeAhead: true, + + initComponent: function(){ + Ext4.apply(this, { + displayField:'cage', + valueField: 'rowid', + queryMode: 'local', + anyMatch: true, + store: Ext4.create('LABKEY.ext4.data.Store', { + type: 'labkey-store', + schemaName: 'ehr_lookups', + queryName: 'cage', + sort: 'cage', + autoLoad: true, + columns: 'rowid,cage', + }) + }); + + if (!Ext4.isDefined(this.initialConfig.multiSelect)){ + this.multiSelect = true; + } + + this.callParent(arguments); + }, + +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/Alias.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/Alias.js new file mode 100644 index 0000000..b0cfbfc --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/Alias.js @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('Alias', { + allQueries: { + + }, + byQuery: { + 'study.alias': { + project: { + hidden: true, + }, + alias: { + allowBlank: false, + nullable: false, + }, + category: { + allowBlank: false, + nullable: false, + } + }, + + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/Arrival.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/Arrival.js new file mode 100644 index 0000000..3e2850b --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/Arrival.js @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.onReady(function() { + // this is to skip Id not found warning during weights entry in Arrival data entry form + if (EHR.data.DataEntryClientStore) { + Ext4.override(EHR.data.DataEntryClientStore, { + getExtraContext: function(){ + return { + skipIdNotFoundError: {'form': 'arrival'} + } + } + }); + } +}); + +EHR.model.DataModelManager.registerMetadata('Arrival', { + allQueries: { + 'endDate': { + hidden: true + } + }, + byQuery: { + 'study.arrival': { + 'cage': { + allowBlank: false, + columnConfig: { + fixed: true, + width: 200 + }, + }, + 'Id/demographics/species': { + columnConfig: { + fixed: true, + width: 200 + }, + allowBlank: false + }, + 'Id/demographics/birth': { + allowBlank: false + }, + 'Id/demographics/gender': { + allowBlank: false + }, + 'Id/demographics/geographic_origin': { + allowBlank: false, + columnConfig: { + fixed: true, + width: 200 + } + }, + project: { + xtype: 'combo', + columnConfig: { + width: 150 + }, + lookup: { + schemaName: 'ehr', + queryName: 'project', + keyColumn: 'project', + columns: 'project,name', + filterArray: [ + LABKEY.Filter.create('isActive', true, LABKEY.Filter.Types.EQUAL), + ] + }, + allowBlank: false + }, + arrivalProtocol: { + allowBlank: false, + columnConfig: { + width: 200 + }, + lookup: { + schemaName: 'ehr', + queryName: 'activeProtocols', + keyColumn: 'protocol', + columns: 'protocol,title' + }, + }, + performedby: { + hidden: true, + showInGrid: false + }, + sourceFacility: { + allowBlank: false, + columnConfig: { + fixed: true, + width: 150 + }, + }, + acquisitionType: { + allowBlank: false, + columnConfig: { + fixed: true, + width: 150 + }, + }, + arrivalType: { + allowBlank: false, + columnConfig: { + width: 200 + } + }, + rearrival: { + allowBlank: true, + hidden: true, + showInGrid: false + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/Assignment.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/Assignment.js new file mode 100644 index 0000000..4db08ad --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/Assignment.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +EHR.model.DataModelManager.registerMetadata('Assignment', { + allQueries: { + endDate: { + hidden: true + } + }, + byQuery: { + 'study.assignment': { + 'project': { + xtype: 'combo', + nullable: false, + lookup: { + schemaName: 'ehr', + queryName: 'project', + keyColumn: 'project', + columns: 'project,name', + filterArray: [ + LABKEY.Filter.create('isActive', true, LABKEY.Filter.Types.EQUAL), + ] + } + } + }, + 'study.protocolAssignment': { + 'project': { + hidden: true + }, + 'protocol': { + xtype: 'combo', + nullable: false, + columnConfig: { + fixed: true, + width: 150 + }, + lookup: { + schemaName: 'ehr', + queryName: 'activeProtocols', + keyColumn: 'protocol', + columns: 'protocol,title' + }, + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/BehaviorDefaults.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/BehaviorDefaults.js new file mode 100644 index 0000000..6a52bea --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/BehaviorDefaults.js @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('BehaviorDefaults', { + byQuery: { + 'study.clinremarks': { + hx: { + formEditorConfig: { + xtype: 'ehr-hxtextarea' + }, + }, + p: { + hidden: true, + }, + s: { + hidden: true, + }, + o: { + hidden: true, + }, + a: { + hidden: true, + }, + remark: { + label: 'Remark', + height: 120 + }, + vetreview: { + hidden: true, + }, + category: { + getInitialValue: function (v, rec) { + return 'Behavior' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + enddate: { + hidden: true + }, + dateFinalized: { + hidden: true + }, + qcstate: { + hidden: true + }, + performedby: { + hidden: false, + defaultValue: LABKEY.Security.currentUser.id.toString(), + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'core', + sql: "SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.PrincipalsWithoutAdmin WHERE active = TRUE AND Type = 'u'", + autoLoad: true + } + } + }, + }, + 'study.clinical_observations': { + type: { + hidden: true, + defaultValue: 'Behavior' + }, + category: { + lookup: { + filterArray: [ + LABKEY.Filter.create('category', 'Behavior') + ] + } + } + }, + 'study.observation_order': { + type: { + hidden: true, + defaultValue: 'Behavior' + }, + category: { + lookup: { + filterArray: [ + LABKEY.Filter.create('category', 'Behavior') + ] + } + } + }, + 'study.drug': { + category: { + defaultValue: 'Behavior', + hidden: true + } + }, + 'study.treatment_order': { + category: { + defaultValue: 'Behavior', + hidden: true + }, + performedby: { + hidden: true + } + }, + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/BehaviorRounds.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/BehaviorRounds.js new file mode 100644 index 0000000..cc9d543 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/BehaviorRounds.js @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('BehaviorRounds', { + allQueries: { + Id: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + date: { + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + caseid: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + } + }, + byQuery: { + 'study.cases': { + Id: { + xtype: 'nbri_ehr-animalIdCases', + inheritFromParent: false, + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + date: { + id: 'open_date', + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + }, + getInitialValue: function(v, rec){ + return null; + } + }, + enddate: { + id: 'close_date', + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + category: { + getInitialValue: function (v, rec){ + return 'Behavior' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + problemCategory: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + problemSubcategory: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + plan: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + openRemark: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + closeRemark: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + performedby: { + hidden: false, + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + formCasesLink: { + xtype: 'nbri_ehr-editCases', + editorConfig: { + readonly: true + } + }, + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/BehavioralCase.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/BehavioralCase.js new file mode 100644 index 0000000..94d26dc --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/BehavioralCase.js @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +EHR.model.DataModelManager.registerMetadata('BehavioralCase', { + allQueries: { + Id: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + date: { + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + caseid: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + } + }, + byQuery: { + 'study.cases': { + Id: { + xtype: 'nbri_ehr-animalIdCases', + inheritFromParent: false, + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + date: { + formEditorConfig: { + id: 'openDate', + } + }, + enddate: { + formEditorConfig: { + id: 'closeDate' + } + }, + category: { + getInitialValue: function (v, rec){ + return 'Behavior' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + problemCategory: { + nullable: false, + editorConfig: { + listeners: { + select: function (field, recs) { + if (!recs || recs.length !== 1) + return; + + var record = EHR.DataEntryUtils.getBoundRecord(field); + if (record) { + var rec = recs[0]; + var meta = record.store.model.prototype.fields.get('problemSubcategory'); + var storeId = LABKEY.ext4.Util.getLookupStoreId(meta); + var store = Ext4.StoreMgr.get(storeId); + if (store) { + store.filterArray = [LABKEY.Filter.create('category', rec.get('value'))]; + store.load(); + } + } + } + } + }, + }, + openRemark: { + height: 120 + }, + plan: { + height: 120 + }, + closeRemark: { + height: 120 + }, + qcstate: { + hidden: true + }, + attachmentFile: { + hidden: true + }, + caseCategory: { + hidden: true + }, + formCasesLink: { + xtype: 'nbri_ehr-editCases' + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/Birth.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/Birth.js new file mode 100644 index 0000000..3f6c865 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/Birth.js @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.onReady(function() { + // this is to skip Id not found warning during weights entry in Birth data entry form + if (EHR.data.DataEntryClientStore) { + Ext4.override(EHR.data.DataEntryClientStore, { + getExtraContext: function(){ + return { + skipIdNotFoundError: {'form': 'birth'} + } + } + }); + } +}); + +EHR.model.DataModelManager.registerMetadata('Birth', { + allQueries: { + 'endDate': { + hidden: true + } + }, + byQuery: { + 'study.birth': { + 'Id/demographics/species': { + allowBlank: false, + columnConfig: { + fixed: true, + width: 250 + } + }, + 'cage': { + allowBlank: false, + columnConfig: { + fixed: true, + width: 200 + }, + }, + project: { + xtype: 'combo', + allowBlank: false, + columnConfig: { + width: 150 + }, + lookup: { + schemaName: 'ehr', + queryName: 'project', + keyColumn: 'project', + columns: 'project,name', + filterArray: [ + LABKEY.Filter.create('isActive', true, LABKEY.Filter.Types.EQUAL), + ] + } + }, + birthProtocol: { + columnConfig: { + width: 200 + }, + allowBlank: false, + lookup: { + schemaName: 'ehr', + queryName: 'activeProtocols', + keyColumn: 'protocol', + columns: 'protocol,title' + }, + }, + 'Id/demographics/birth': { + allowBlank: false + }, + 'Id/demographics/gender': { + allowBlank: false + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/BulkBehavior.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/BulkBehavior.js new file mode 100644 index 0000000..631b913 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/BulkBehavior.js @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('BulkBehavior', { + byQuery: { + 'study.clinremarks': { + hx: { + formEditorConfig: { + xtype: 'ehr-hxtextarea' + }, + }, + p: { + hidden: true, + }, + s: { + hidden: true, + }, + o: { + hidden: true, + }, + a: { + hidden: true, + }, + remark: { + label: 'Remark', + height: 120 + }, + vetreview: { + hidden: true, + }, + category: { + getInitialValue: function (v, rec) { + return 'Behavior' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + enddate: { + hidden: true + }, + dateFinalized: { + hidden: true + }, + qcstate: { + hidden: true + } + }, + 'study.clinical_observations': { + type: { + hidden: true, + defaultValue: 'Behavior' + } + }, + 'study.observation_order': { + type: { + hidden: true, + defaultValue: 'Behavior' + } + }, + 'study.treatment_order': { + category: { + defaultValue: 'Behavior', + hidden: true + }, + performedby: { + hidden: true + } + }, + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/BulkClinical.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/BulkClinical.js new file mode 100644 index 0000000..fb747b2 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/BulkClinical.js @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('BulkClinical', { + byQuery: { + 'study.clinremarks': { + p: { + columnConfig: { + width: 250 + } + }, + vetreview: { + columnConfig: { + width: 250 + } + }, + vetreviewdate: { + columnConfig: { + width: 200 + } + }, + dateFinalized: { + columnConfig: { + width: 200 + } + }, + hx: { + hidden: true + }, + remark: { + allowBlank: true + }, + category: { + getInitialValue: function (v, rec) { + return 'Clinical' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalCase.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalCase.js new file mode 100644 index 0000000..4edd8e4 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalCase.js @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +EHR.model.DataModelManager.registerMetadata('ClinicalCase', { + allQueries: { + Id: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + date: { + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + caseid: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + } + }, + byQuery: { + 'study.cases': { + Id: { + xtype: 'nbri_ehr-animalIdCases', + inheritFromParent: false, + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + date: { + formEditorConfig: { + id: 'openDate', + } + }, + enddate: { + formEditorConfig: { + id: 'closeDate' + } + }, + category: { + getInitialValue: function (v, rec){ + return 'Clinical' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + problemCategory: { + nullable: false, + editorConfig: { + listeners: { + select: function (field, recs) { + if (!recs || recs.length !== 1) + return; + + var record = EHR.DataEntryUtils.getBoundRecord(field); + if (record) { + var rec = recs[0]; + var meta = record.store.model.prototype.fields.get('problemSubcategory'); + var storeId = LABKEY.ext4.Util.getLookupStoreId(meta); + var store = Ext4.StoreMgr.get(storeId); + if (store) { + store.filterArray = [LABKEY.Filter.create('category', rec.get('value'))]; + store.load(); + } + } + } + } + }, + }, + openRemark: { + height: 120 + }, + plan: { + height: 120 + }, + closeRemark: { + height: 120 + }, + qcstate: { + hidden: true + }, + attachmentFile: { + hidden: true + }, + caseCategory: { + hidden: true + }, + formCasesLink: { + xtype: 'nbri_ehr-editCases' + } + }, + 'study.clinremarks': { + hx: { + formEditorConfig: { + xtype: 'ehr-hxtextarea' + }, + }, + p: { + height: 120 + }, + remark: { + label: 'Remark', + height: 120 + }, + vetreview: { + height: 120 + }, + category: { + getInitialValue: function (v, rec) { + return 'Clinical' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + performedby: { + hidden: false, + defaultValue: LABKEY.Security.currentUser.id.toString(), + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'core', + sql: "SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.PrincipalsWithoutAdmin WHERE active = TRUE AND Type = 'u'", + autoLoad: true + } + } + }, + enddate: { + hidden: true + }, + dateFinalized: { + hidden: true + }, + qcstate: { + hidden: true + }, + }, + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalDefaults.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalDefaults.js new file mode 100644 index 0000000..7a7e901 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalDefaults.js @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('ClinicalDefaults', { + byQuery: { + 'study.treatment_order': { + category: { + defaultValue: 'Clinical', + hidden: true + }, + performedby: { + hidden: true + }, + enddate: { + allowBlank: true, + } + }, + 'study.prc_order': { + category: { + defaultValue: 'Clinical', + hidden: true + }, + performedby: { + hidden: true + }, + windowStart: { + columnConfig: { + fixed: true, + width: 150 + }, + getInitialValue: function(v, rec){ + if (v) + return v; + + return new Date(); + } + }, + windowEnd: { + columnConfig: { + fixed: true, + width: 150 + }, + getInitialValue: function(v, rec){ + if (v) + return v; + + let ret = Ext4.Date.clearTime(new Date()); + ret = Ext4.Date.add(ret, Ext4.Date.DAY, 1); + ret.setHours(8); + return ret; + } + }, + procedure: { + lookup: { + filterArray: [LABKEY.Filter.create('active', true, LABKEY.Filter.Types.EQUAL)] + }, + columnConfig: { + width: 250 + } + } + }, + 'study.drug': { + category: { + defaultValue: 'Clinical', + hidden: true + }, + date: { + header: 'Date/Time', + } + }, + 'study.prc': { + category: { + defaultValue: 'Clinical', + hidden: true + }, + // procedure data is not categorized, so not using procedure_category based selection + procedure: { + lookup: { + filterArray: [LABKEY.Filter.create('active', true, LABKEY.Filter.Types.EQUAL)] + }, + columnConfig: { + width: 250 + } + }, + orderid: { + hidden: true + } + }, + 'study.clinremarks': { + category: { + defaultValue: 'Clinical', + hidden: true, + allowBlank: false + } + }, + 'study.blood': { + reason: { + defaultValue: 'Clinical', + hidden: true + }, + category: { + defaultValue: 'Clinical', + hidden: true, + allowBlank: false + }, + units: { + hidden: true + } + }, + 'study.cases': { + openRemark: { + height: 120 + }, + plan: { + height: 120 + }, + closeRemark: { + height: 120 + }, + qcstate: { + hidden: true + }, + attachmentFile: { + hidden: true + }, + category: { + hidden: true + }, + caseCategory: { + hidden: true + }, + formCasesLink: { + xtype: 'nbri_ehr-editCases' + } + }, + 'study.clinremarks': { + hx: { + formEditorConfig: { + xtype: 'ehr-hxtextarea' + }, + }, + p: { + height: 120 + }, + remark: { + label: 'Remark', + height: 120 + }, + vetreview: { + height: 120 + }, + category: { + getInitialValue: function (v, rec) { + return 'Clinical' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + enddate: { + hidden: true + }, + dateFinalized: { + hidden: true + }, + qcstate: { + hidden: true + }, + }, + + 'study.clinical_observations': { + type: { + hidden: true, + defaultValue: 'Clinical' + }, + category: { + lookup: { + columns: 'value,description', + filterArray: [ + LABKEY.Filter.create('category', null, LABKEY.Filter.Types.ISBLANK) + ], + } + }, + }, + 'study.vitals': { + category: { + defaultValue: 'Clinical', + hidden: true + }, + units: { + hidden: true + } + }, + 'study.observation_order': { + type: { + hidden: true, + defaultValue: 'Clinical' + }, + category: { + lookup: { + columns: 'value,description', + filterArray: [ + LABKEY.Filter.create('category', null, LABKEY.Filter.Types.ISBLANK) + ], + } + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalRounds.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalRounds.js new file mode 100644 index 0000000..c8464bd --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/ClinicalRounds.js @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('ClinicalRounds', { + allQueries: { + Id: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + date: { + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + caseid: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + } + }, + byQuery: { + 'study.cases': { + Id: { + xtype: 'nbri_ehr-animalIdCases', + inheritFromParent: false, + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + date: { + id: 'open_date', + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + }, + getInitialValue: function(v, rec){ + return null; + } + }, + enddate: { + id: 'close_date', + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + category: { + getInitialValue: function (v, rec){ + return 'Clinical' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + problemCategory: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + problemSubcategory: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + plan: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + openRemark: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + closeRemark: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + performedby: { + hidden: false, + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + formCasesLink: { + xtype: 'nbri_ehr-editCases', + editorConfig: { + readonly: true + } + }, + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/DeathNecropsy.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/DeathNecropsy.js new file mode 100644 index 0000000..cb988e9 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/DeathNecropsy.js @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('DeathNecropsy', { + allQueries: { + }, + byQuery: { + 'study.deaths': { + qcstate: { + hidden: true + }, + date: { + xtype: 'xdatetime', + editorConfig: { + dateFormat: 'Y-m-d', + timeFormat: 'H:i' + }, + }, + deathWeight: { + label: 'Weight (kg)', + allowBlank: false, + nullable: false, + }, + reason: { + allowBlank: false, + nullable: false, + } + }, + 'study.necropsy': { + date: { + label: 'Exam Date', + xtype: 'xdatetime', + editorConfig: { + dateFormat: 'Y-m-d', + timeFormat: 'H:i', + listeners: { + change: function (combo, rec) { + const panel = combo.up('ehr-dataentrypanel'); + if (panel) { + const date = panel.down('datefield')?.value; + const store = panel.storeCollection.getClientStoreByName('grossPathology'); + if (store && date) { + store.data.each(function (dateRec) { + dateRec.set('date', rec); + }, this); + } + + const store2 = panel.storeCollection.getClientStoreByName('tissueDisposition'); + if (store2 && date) { + store2.data.each(function (dateRec) { + dateRec.set('date', rec); + }, this); + } + } + } + } + } + }, + grossAbnormalities: { + xtype: 'ehr-remarkfield', + height: 100, + editorConfig: { + resizeDirections: 's' + }, + columnConfig: { + width: 200 + } + }, + diagnosis: { + xtype: 'ehr-remarkfield', + label: 'Diagnosis', + resizeDirections: 's', + height: 100, + columnConfig: { + width: 200 + }, + }, + relevantHistory: { + xtype: 'ehr-remarkfield', + label: 'Relevant History', + resizeDirections: 's', + height: 100, + columnConfig: { + width: 200, + } + }, + attachmentFile: { + hidden: true + }, + category: { + hidden: true + }, + qcstate: { + hidden: true + } + }, + 'study.grossPathology': { + date: { + hidden: true, + getInitialValue: function(v, rec){ + const necropsyStore = rec.storeCollection.getClientStoreByName('necropsy'); + if (necropsyStore?.data?.items.length > 0) { + return necropsyStore.data.items[0].data.date; + } + } + }, + remark: { + hidden: true, + showInGrid: false + }, + project: { + hidden: true, + showInGrid: false + }, + systemExamined: { + columnConfig: { + width: 200 + } + }, + performedby: { + hidden: true, + showInGrid: false + }, + appearance: { + defaultValue: 'Normal', + lookup: { + schemaName: 'ehr_lookups', + queryName: 'necropsy_organ_appearance', + keyColumn: 'title', + displayColumn: 'title', + defaultValue: 'Normal' + } + } + }, + 'study.tissueDisposition': { + date: { + hidden: true, + getInitialValue: function(v, rec){ + const necropsyStore = rec.storeCollection.getClientStoreByName('necropsy'); + if (necropsyStore) { + return necropsyStore.data.items[0].data.date; + } + } + }, + project: { + hidden: true, + showInGrid: false + }, + performedby: { + hidden: true, + showInGrid: false + }, + necropsyDispositionCode: { + columnConfig: { + fixed: true, + width: 200 + }, + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/MedicationEndDate.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/MedicationEndDate.js new file mode 100644 index 0000000..fd4a5ec --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/MedicationEndDate.js @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('MedicationEndDate', { + allQueries: { + 'code': { + editorConfig: { + listeners: { + // End date calculated from Default Duration in the formulary and the date field of data entry grid. + // Only calculate end date when treatment is selected and there is a date in the field. + // Don’t recalculate if changing drug multiple times. + change: function (field, newVal, oldVal) { + if (newVal && !oldVal) { + let record = EHR.DataEntryUtils.getBoundRecord(field); + if (record) { + LABKEY.Query.selectRows({ + schemaName: 'ehr_lookups', + queryName: 'drug_defaults', + columns: ['duration','offset'], + scope: this, + ignoreFilter: true, + filterArray: [LABKEY.Filter.create('code', newVal)], + success: function (data) { + if (data.rows && data.rows.length > 0) { + let defaultDuration = data.rows[0].duration; + let offset = data.rows[0].offset; + let date = record.get('date'); + if (defaultDuration && date) { + let endDate = new Date(date); + endDate.setDate(endDate.getDate() + defaultDuration); + if (offset) { + endDate.setHours(endDate.getHours() + offset); + } + EHR.DataEntryUtils.setSiblingFields(field, { + enddate: endDate + }); + } + } + }, + failure: function(error) { + console.error(error); + } + }); + } + } + } + } + } + } + }, +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/NBRIDefault.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/NBRIDefault.js new file mode 100644 index 0000000..c5971be --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/NBRIDefault.js @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('Default', { + allQueries: { + Id: { + xtype: 'ehr-animalIdUpperField', + }, + 'Id/demographics/dam': { + xtype: 'ehr-animalIdUpperField', + }, + 'Id/demographics/sire': { + xtype: 'ehr-animalIdUpperField', + }, + performedby: { + hidden: false, + allowBlank: true, + defaultValue: LABKEY.Security.currentUser.id, + getInitialValue: function (v, rec) { + if (Number.isInteger(Number(v))){ + return v; + } + + return LABKEY.Security.currentUser.id; + }, + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'core', + + // 'performedby' is a text field in the dataset and its lookup to the userid is an int field - this mismatch causes it to disappear + // from the display when a value is selected from the dropdown even though the 'userid' value gets saved as a text (this behavior was only seen + // in the form panel but not in the grid panel). + // casting it as a varchar when loading the store fixes this issue. + sql: "SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.PrincipalsWithoutAdmin WHERE active = TRUE AND Type = 'u'", + autoLoad: true + } + } + }, + orderedby: { + hidden: false, + allowBlank: false, + defaultValue: null, + columnConfig: { + width: 160 + }, + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'ehr_lookups', + + // 'orderedby' is a text field in the dataset and its lookup to the userid is an int field - this mismatch causes it to disappear + // from the display when a value is selected from the dropdown even though the 'userid' value gets saved as a text. + // Casting it as a varchar when loading the store fixes this issue. + sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName FROM ehr_lookups.veterinarians', + autoLoad: true + } + } + }, + scheduleddate: { + header: 'Scheduled Date/Time', + label: 'Scheduled Date/Time', + hidden: false, + userEditable: false, + nullable: true, + columnConfig: { + width: 180 + } + }, + date: { + columnConfig: { + fixed: true, + width: 150 + } + }, + enddate: { + columnConfig: { + fixed: true, + width: 150 + } + }, + 'cage': { + columnConfig: { + fixed: true, + width: 150 + }, + }, + QCState: { + hidden: true, + editable: false, + editorConfig: { + hidden: true, + editable: false + }, + getInitialValue: function (v) { + var qc; + if (!v && EHR.Security.getQCStateByLabel('In Progress')) + qc = EHR.Security.getQCStateByLabel('In Progress').RowId; + return v || qc || 'In Progress'; + } + }, + 'qcstate/label': { + hidden: true, + editable: false, + editorConfig: { + hidden: true, + editable: false + } + } + }, + byQuery: { + 'study.housing': { + room: { + allowBlank: true, + hidden: true + }, + 'cage': { + allowBlank: false + }, + 'enddate': { + hidden: true + }, + reason: { + defaultValue: null, + allowBlank: false, + columnConfig: { + width: 180 + }, + lookup: { + filterArray: [LABKEY.Filter.create('date_disabled', null, LABKEY.Filter.Types.ISBLANK)] + } + }, + performedby: { + hidden: false, + allowBlank: true, + defaultValue: LABKEY.Security.currentUser.id, + lookup: { + schemaName: 'core', + queryName: 'users', + keyColumn: 'UserId', + displayColumn: 'DisplayName', + columns: 'UserId,DisplayName,FirstName,LastName', + sort: 'Type,DisplayName' + }, + getInitialValue: function (v, rec) { + if (Number.isInteger(Number(v))){ + return v; + } + + return LABKEY.Security.currentUser.id; + }, + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'core', + + // 'performedby' is a text field in the dataset and its lookup to the userid is an int field - this mismatch causes it to disappear + // from the display when a value is selected from the dropdown even though the 'userid' value gets saved as a text (this behavior was only seen + // in the form panel but not in the grid panel). + // casting it as a varchar when loading the store fixes this issue. + sql: "SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.PrincipalsWithoutAdmin WHERE active = TRUE AND Type = 'u'", + autoLoad: true + } + } + }, + }, + 'study.arrival': { + initialRoom: { + allowBlank: true, + hidden: true + } + }, + 'study.birth': { + room: { + allowBlank: true, + hidden: true + } + }, + 'study.exemptions': { + category: { + columnConfig: { + width: 300 + } + } + }, + 'study.notes': { + remark: { + hidden: false, + columnConfig: { + width: 400 + } + } + }, + 'study.treatment_order': { + endTreatmentOrderedBy: { + columnConfig: { + width: 200 + }, + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'ehr_lookups', + + // see 'orderedby' comment above. + sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName FROM ehr_lookups.veterinarians', + autoLoad: true + } + } + }, + frequency: { + columnConfig: { + width: 180 + }, + nullable: false, + allowBlank: true, + lookup: { + filterArray: [LABKEY.Filter.create('active', true, LABKEY.Filter.Types.EQUAL)] + }, + } + }, + 'study.drug': { + treatmentid: { + hidden: true, + nullable: true + }, + performedby: { + allowBlank: true, + } + }, + 'study.observation_order': { + category: { + allowBlank: false, + editorConfig: { + plugins: [Ext4.create('LDK.plugin.UserEditableCombo', { + allowChooseOther: false + })] + }, + lookup: { + columns: 'value,description' + }, + columnConfig: { + width: 200 + } + }, + area: { + defaultValue: 'N/A', + columnConfig: { + width: 200 + } + }, + observation: { + columnConfig: { + width: 200 + } + }, + remark: { + columnConfig: { + width: 300 + } + }, + frequency: { + columnConfig: { + width: 180 + }, + nullable: false, + allowBlank: true, + lookup: { + filterArray: [LABKEY.Filter.create('active', true, LABKEY.Filter.Types.EQUAL)] + }, + } + }, + 'study.pairings': { + date: { + header: 'Start Date', + getInitialValue: function(v, rec){ + if (v) + return v; + + return new Date(); + } + }, + type: { + hidden: true + }, + pairid: { + hidden: false, + nullable: false, + columnConfig: { + width: 150 + }, + }, + formationType: { + columnConfig: { + width: 150 + } + }, + reason: { + columnConfig: { + width: 150 + }, + }, + goal: { + columnConfig: { + width: 150 + }, + }, + endState: { + columnConfig: { + width: 150 + }, + }, + remark: { + title: 'Remark on Formation', + columnConfig: { + width: 200 + } + }, + separationRemark: { + columnConfig: { + width: 200 + } + } + }, + 'study.flags': { + flag: { + allowBlank: false, + lookup: { + columns: 'objectid,value,category,code', + sort: 'category,code,value', + filterArray: [LABKEY.Filter.create('datedisabled', null, LABKEY.Filter.Types.ISBLANK)] + }, + columnConfig: { + width: 300 + }, + editorConfig: { + caseSensitive: false, + anyMatch: true, + plugins: [Ext4.create('LDK.plugin.UserEditableCombo', { + allowChooseOther: false + })], + listConfig: { + innerTpl: '{[(values.category ? ("" + LABKEY.Utils.encodeHtml(values.category) + ": ") : "") + LABKEY.Utils.encodeHtml(values.value)]}', + getInnerTpl: function () { + return this.innerTpl; + } + } + } + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/ObsDefaults.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/ObsDefaults.js new file mode 100644 index 0000000..bd9f4ce --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/ObsDefaults.js @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('ObsDefaults', { + byQuery: { + 'study.clinical_observations': { + category: { + lookup: { + columns: 'value,description', + filterArray: [] + } + }, + }, + 'study.observation_order': { + category: { + lookup: { + columns: 'value,description', + filterArray: [] + } + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/ParentChild.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/ParentChild.js new file mode 100644 index 0000000..b47c99a --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/ParentChild.js @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('ParentChild', { + allQueries: { + Id: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + caseid: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + } + } +}); diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/Pregnancy.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/Pregnancy.js new file mode 100644 index 0000000..72bb07a --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/Pregnancy.js @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('Pregnancy', { + allQueries: { + + }, + byQuery: { + 'study.pregnancy': { + project: { + hidden: true, + }, + type: { + hidden: true, + }, + diagnosis: { + hidden: true, + }, + attachmentFile: { + hidden: true, + }, + result: { + allowBlank: false, + nullable: false, + } + }, + + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/Rearrival.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/Rearrival.js new file mode 100644 index 0000000..059847e --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/Rearrival.js @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +EHR.model.DataModelManager.registerMetadata('Rearrival', { + + byQuery: { + 'study.arrival': { + rearrival: { + getInitialValue: function (v, rec) { + return true + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + performedby: { + hidden: true, + showInGrid: false + }, + sourceFacility: { + allowBlank: false, + columnConfig: { + fixed: true, + width: 150 + }, + }, + acquisitionType: { + allowBlank: false, + columnConfig: { + fixed: true, + width: 150 + }, + }, + arrivalType: { + allowBlank: false, + columnConfig: { + width: 200 + } + }, + 'cage': { + allowBlank: true, + hidden: true, + showInGrid: false + }, + project: { + allowBlank: true, + hidden: true, + showInGrid: false + }, + arrivalProtocol: { + allowBlank: true, + hidden: true, + showInGrid: false + }, + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/TreatmentSchedule.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/TreatmentSchedule.js new file mode 100644 index 0000000..4c1dc1f --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/TreatmentSchedule.js @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('TreatmentSchedule', { + allQueries: { + project: { + hidden: true, + allowBlank: true + }, + code: { + allowBlank: false, + inheritFromParent: false, + editorConfig: { + xtype: 'labkey-combo', + displayField: 'meaning', + valueField: 'code', + anyMatch: true, + queryMode: 'local', + store: { + type: 'labkey-store', + schemaName: 'ehr_lookups', + queryName: 'snomed', + columns: 'code,meaning', + sort: 'meaning,code', + filterArray: [LABKEY.Filter.create('dateDisabled', null, LABKEY.Filter.Types.ISBLANK)], + autoLoad: true, + getRecordForCode: function(code){ + debugger + var recIdx = this.findExact('code', code); + if (recIdx !== -1){ + return this.getAt(recIdx); + } + } + } + } + }, + volume: { + inheritFromParent: false, + shownInGrid: true, + compositeField: 'Volume', + xtype: 'nbri_ehr-drugvolumefield', + noSaveInTemplateByDefault: true, + editorConfig: { + decimalPrecision: 3 + }, + header: 'Vol', + columnConfig: { + width: 90 + } + }, + type: { + hidden: true + }, + attachmentFile: { + hidden: true + } + }, + byQuery: { + 'study.drug': { + date: { + header: 'Date/Time', + } + }, + 'study.treatment_order': { + enddate: { + allowBlank: true, + } + } + } +}); \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/nbri.css b/nbri_ehr/resources/web/nbri_ehr/nbri.css new file mode 100644 index 0000000..fe5808a --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/nbri.css @@ -0,0 +1,7 @@ + +input.form-panel-input-disabled, +textarea.form-panel-input-disabled, +label.form-panel-input-disabled { + color: gray; + opacity: 1 !important; +} \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/nbriOverrides.js b/nbri_ehr/resources/web/nbri_ehr/nbriOverrides.js new file mode 100644 index 0000000..02fec2b --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/nbriOverrides.js @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.Utils.rowEditorPlugin = 'NBRI_EHR.plugin.RowEditor'; + +EHR.Utils.editUIButtonHandler = function(schemaName, queryName, dataRegionName, paramMap, copyFilters){ + var params = { + schemaName: schemaName, + 'query.queryName': queryName, + showImport: false + }; + + this.editUIButtonCore(schemaName, queryName, dataRegionName, paramMap, undefined, params); +}; \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/nbriReports.js b/nbri_ehr/resources/web/nbri_ehr/nbriReports.js new file mode 100644 index 0000000..0b54d23 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/nbriReports.js @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.namespace('EHR.reports'); + +EHR.reports.clinicalHistoryPanelXtype = 'nbri_ehr-snapshotpanel'; + + +EHR.reports.snapshot = function(panel, tab, showActionsBtn){ + if (tab.filters.subjects){ + renderSubjects(tab.filters.subjects, tab); + } + else + { + panel.resolveSubjectsFromHousing(tab, renderSubjects, this); + } + + function renderSubjects(subjects, tab){ + var toAdd = []; + if (!subjects.length){ + toAdd.push({ + html: 'No animals were found.', + border: false + }); + } + else if (subjects.length < 10) { + for (var i=0;i
If there have been recent blood draws for the animal, a graph will show the available blood over time. On the graph, dots indicate dates when either blood was drawn or a previous blood draw fell off. The horizontal lines indicate the maximum allowable blood that can be drawn on that date.', + border: false, + style: 'padding-bottom: 20px;' + }); + + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom: 10px;', + queryConfig: panel.getQWPConfig({ + title: 'Summary', + schemaName: 'study', + queryName: 'Demographics', + viewName: 'Blood Draws', + filterArray: filterArray.removable.concat(filterArray.nonRemovable) + }) + }); + + var subjects = tab.filters.subjects || []; + + if (subjects.length){ + tab.add({ + xtype: 'nbri-bloodsummarypanel', + subjects: subjects + }); + } + else + { + panel.resolveSubjectsFromHousing(tab, function(subjects, tab){ + tab.add({ + xtype: 'nbri-bloodsummarypanel', + subjects: subjects + }); + }, this); + } +}; + +EHR.reports.clinicalHistory = function(panel, tab, showActionsBtn, includeAll){ + if (tab.filters.subjects){ + renderSubjects(tab.filters.subjects, tab); + } + else + { + panel.resolveSubjectsFromHousing(tab, renderSubjects, this); + } + + function renderSubjects(subjects, tab){ + if (subjects.length > 10){ + tab.add({ + html: 'Because more than 10 subjects were selected, the condensed report is being shown. Note that you can click the animal ID to open this same report in a different tab, showing that animal in more detail or click the link labeled \'Show Hx\'.', + style: 'padding-bottom: 20px;', + border: false + }); + + var filterArray = panel.getFilterArray(tab); + var title = panel.getTitleSuffix(); + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: { + title: 'Overview' + title, + schemaName: 'study', + queryName: 'demographics', + viewName: 'Snapshot', + filterArray: filterArray.removable.concat(filterArray.nonRemovable) + } + }); + + return; + } + + if (!subjects.length){ + tab.add({ + html: 'No animals were found.', + border: false + }); + + return; + } + + tab.addCls('ehr-snapshotsubpanel'); + + var minDate = includeAll ? null : Ext4.Date.add(new Date(), Ext4.Date.YEAR, -30); + var toAdd = []; + Ext4.each(subjects, function(s){ + toAdd.push({ + html: 'Animal: ' + Ext4.htmlEncode(s) + '', + style: 'padding-bottom: 20px;', + border: false + }); + + toAdd.push({ + xtype: EHR.reports.clinicalHistoryPanelXtype, + showActionsButton: !!showActionsBtn, + hrefTarget: '_blank', + border: false, + subjectId: s + }); + + toAdd.push({ + html: 'Chronological History:
', + style: 'padding-top: 5px;', + border: false + }); + + toAdd.push({ + xtype: 'nbri_ehr-clinicalhistorypanel', + border: true, + subjectId: s, + autoLoadRecords: true, + minDate: minDate, + //maxGridHeight: 1000, + hrefTarget: '_blank', + style: 'margin-bottom: 20px;' + }); + }, this); + + if (toAdd.length){ + tab.add(toAdd); + } + } +}; + +EHR.reports.observationSchedule = function(panel, tab, viewName){ + var filterArray = panel.getFilterArray(tab); + var title = panel.getTitleSuffix(); + + var date = Ext4.Date.format(new Date(), LABKEY.extDefaultDateFormat); + tab.add({ + xtype: 'ldk-querypanel', + style: 'margin-bottom:20px;', + queryConfig: panel.getQWPConfig({ + schemaName: 'study', + queryName: 'observationSchedule', + title: 'Observation Schedule ' + title, + filters: filterArray.nonRemovable, + removeableFilters: filterArray.removable, + parameters: { + StartDate: date, + NumDays: 1 + } + }) + }); +} + +EHR.reports.incompleteTreatments = function(panel, tab, viewName){ + const currentDate = new Date(); + const previousDate = new Date(); + previousDate.setDate(currentDate.getDate() - 30); + + const gridFilterArray = panel.getFilterArray(tab); + const filterArray = gridFilterArray.nonRemovable.concat(LABKEY.Filter.create('treatmentStatus', "Completed", LABKEY.Filter.Types.NEQ_OR_NULL)); + + const config = panel.getQWPConfig({ + title: 'Incomplete Treatments For Past 30 Days', + schemaName: 'study', + queryName: 'treatmentSchedule', + dataRegionName: 'incomplete_treatments', + parameters: { + StartDate: `${String(previousDate.getMonth() + 1).padStart(2, '0')}/${String(previousDate.getDate()).padStart(2, '0')}/${previousDate.getFullYear()}`, + NumDays: 30 + }, + filters: filterArray, + removeableFilters: gridFilterArray.removable, + frame: true + }); + + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); +} + +EHR.reports.incompleteObservations = function(panel, tab, viewName){ + const currentDate = new Date(); + const previousDate = new Date(); + previousDate.setDate(currentDate.getDate() - 30); + + const gridFilterArray = panel.getFilterArray(tab); + const filterArray = gridFilterArray.nonRemovable.concat( + [LABKEY.Filter.create('status', "Completed", LABKEY.Filter.Types.DOES_NOT_CONTAIN), + ] + ); + + const config = panel.getQWPConfig({ + title: 'Incomplete Observations For Past 30 Days', + schemaName: 'study', + queryName: 'observationSchedule', + dataRegionName: 'incomplete_observations', + parameters: { + StartDate: `${String(previousDate.getMonth() + 1).padStart(2, '0')}/${String(previousDate.getDate()).padStart(2, '0')}/${previousDate.getFullYear()}`, + NumDays: 30 + }, + filters: filterArray, + removeableFilters: gridFilterArray.removable, + frame: true + }); + + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); +} \ No newline at end of file diff --git a/nbri_ehr/resources/web/nbri_ehr/nbri_ehr_api.lib.xml b/nbri_ehr/resources/web/nbri_ehr/nbri_ehr_api.lib.xml new file mode 100644 index 0000000..b75e07e --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/nbri_ehr_api.lib.xml @@ -0,0 +1,9 @@ + + +