diff --git a/README.md b/README.md index 674b18452..b976212a7 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,7 @@ This is the list of currently supported domains in their loading order: 1. [Bahmni Appointment Specialities (CSV files)](readme/appointmentspecialities.md) 1. [Bahmni Appointment Service Definitions (CSV files)](readme/appointmentservices.md#domain-appointmentservicedefinitions) 1. [Bahmni Appointment Service Types (CSV files)](readme/appointmentservices.md#domain-appointmentservicetypes) +1. [Queues (CSV files)](readme/queues.md#domain-queues) 1. [Data Filter Entity-Basis Mappings (CSV files)](readme/datafiltermappings.md) 1. [Metadata Sets (CSV files)](readme/mdm.md#domain-metadatasets) 1. [Metadata Set Members (CSV files)](readme/mdm.md#domain-metadatasetmembers) @@ -188,6 +189,7 @@ See the [documentation on Initializer's logging properties](readme/rtprops.md#lo ## Releases notes #### Version 2.7.0 +* Added support for Queues #### Version 2.6.0 * Added support for Cohort Attribute types diff --git a/api-2.3/pom.xml b/api-2.3/pom.xml index 51f5d3a04..e3b88098f 100644 --- a/api-2.3/pom.xml +++ b/api-2.3/pom.xml @@ -66,6 +66,13 @@ org.openmrs.module openconceptlab-api + + + org.openmrs.module + queue-api + ${queueVersion} + provided + diff --git a/api-2.3/src/main/java/org/openmrs/module/initializer/api/queues/QueueCsvParser.java b/api-2.3/src/main/java/org/openmrs/module/initializer/api/queues/QueueCsvParser.java new file mode 100644 index 000000000..aa0d2989c --- /dev/null +++ b/api-2.3/src/main/java/org/openmrs/module/initializer/api/queues/QueueCsvParser.java @@ -0,0 +1,44 @@ +package org.openmrs.module.initializer.api.queues; + +import org.apache.commons.lang3.StringUtils; +import org.openmrs.annotation.OpenmrsProfile; +import org.openmrs.module.initializer.Domain; +import org.openmrs.module.initializer.api.BaseLineProcessor; +import org.openmrs.module.initializer.api.CsvLine; +import org.openmrs.module.initializer.api.CsvParser; +import org.openmrs.module.queue.api.QueueService; +import org.openmrs.module.queue.model.Queue; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +@OpenmrsProfile(modules = { "queue:*" }) +public class QueueCsvParser extends CsvParser> { + + private final QueueService queueService; + + @Autowired + public QueueCsvParser(@Qualifier("queue.QueueService") QueueService queueService, QueueLineProcessor processor) { + super(processor); + this.queueService = queueService; + } + + @Override + public Domain getDomain() { + return Domain.QUEUES; + } + + @Override + public Queue bootstrap(CsvLine line) throws IllegalArgumentException { + String uuid = line.getUuid(); + Queue queue = queueService.getQueueByUuid(uuid).orElse(new Queue()); + if (StringUtils.isNotBlank(uuid)) { + queue.setUuid(uuid); + } + return queue; + } + + @Override + public Queue save(Queue instance) { + return queueService.createQueue(instance); + } +} diff --git a/api-2.3/src/main/java/org/openmrs/module/initializer/api/queues/QueueLineProcessor.java b/api-2.3/src/main/java/org/openmrs/module/initializer/api/queues/QueueLineProcessor.java new file mode 100644 index 000000000..d675ceecd --- /dev/null +++ b/api-2.3/src/main/java/org/openmrs/module/initializer/api/queues/QueueLineProcessor.java @@ -0,0 +1,58 @@ +package org.openmrs.module.initializer.api.queues; + +import org.apache.commons.lang3.StringUtils; +import org.openmrs.annotation.OpenmrsProfile; +import org.openmrs.api.ConceptService; +import org.openmrs.api.LocationService; +import org.openmrs.module.initializer.api.BaseLineProcessor; +import org.openmrs.module.initializer.api.CsvLine; +import org.openmrs.module.initializer.api.utils.Utils; +import org.openmrs.module.queue.model.Queue; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +/** + * This is the first level line processor for a Queue + */ +@OpenmrsProfile(modules = { "queue:*" }) +public class QueueLineProcessor extends BaseLineProcessor { + + protected static String HEADER_SERVICE = "service"; + + protected static String HEADER_LOCATION = "location"; + + private final ConceptService conceptService; + + private final LocationService locationService; + + @Autowired + public QueueLineProcessor(@Qualifier("conceptService") ConceptService conceptService, + @Qualifier("locationService") LocationService locationService) { + super(); + this.conceptService = conceptService; + this.locationService = locationService; + } + + @Override + public Queue fill(Queue queue, CsvLine line) throws IllegalArgumentException { + queue.setName(line.get(HEADER_NAME, true)); + queue.setDescription(line.getString(HEADER_DESC)); + if (line.containsHeader(HEADER_SERVICE)) { + String service = line.getString(HEADER_SERVICE); + if (StringUtils.isNotBlank(service)) { + queue.setService(Utils.fetchConcept(service, conceptService)); + } else { + queue.setService(null); + } + } + if (line.containsHeader(HEADER_LOCATION)) { + String location = line.getString(HEADER_LOCATION); + if (StringUtils.isNotBlank(location)) { + queue.setLocation(Utils.fetchLocation(location, locationService)); + } else { + queue.setLocation(null); + } + } + return queue; + } +} diff --git a/api-2.3/src/main/java/org/openmrs/module/initializer/api/queues/QueueLoader.java b/api-2.3/src/main/java/org/openmrs/module/initializer/api/queues/QueueLoader.java new file mode 100644 index 000000000..5c01970c2 --- /dev/null +++ b/api-2.3/src/main/java/org/openmrs/module/initializer/api/queues/QueueLoader.java @@ -0,0 +1,15 @@ +package org.openmrs.module.initializer.api.queues; + +import org.openmrs.annotation.OpenmrsProfile; +import org.openmrs.module.initializer.api.loaders.BaseCsvLoader; +import org.openmrs.module.queue.model.Queue; +import org.springframework.beans.factory.annotation.Autowired; + +@OpenmrsProfile(modules = { "queue:*" }) +public class QueueLoader extends BaseCsvLoader { + + @Autowired + public void setParser(QueueCsvParser parser) { + this.parser = parser; + } +} diff --git a/api-2.3/src/test/java/org/openmrs/module/initializer/DomainBaseModuleContextSensitive_2_3_Test.java b/api-2.3/src/test/java/org/openmrs/module/initializer/DomainBaseModuleContextSensitive_2_3_Test.java index cc58c3dd3..19f3f997d 100644 --- a/api-2.3/src/test/java/org/openmrs/module/initializer/DomainBaseModuleContextSensitive_2_3_Test.java +++ b/api-2.3/src/test/java/org/openmrs/module/initializer/DomainBaseModuleContextSensitive_2_3_Test.java @@ -9,12 +9,26 @@ */ package org.openmrs.module.initializer; +import org.openmrs.module.Module; +import org.openmrs.module.ModuleFactory; + +import java.io.File; + /** * This allows to perform Spring context sensitive tests when Data Filter API is a dependency. In * that case it is necessary for each context sensitive test to update the search index. */ public abstract class DomainBaseModuleContextSensitive_2_3_Test extends DomainBaseModuleContextSensitiveTest { + public DomainBaseModuleContextSensitive_2_3_Test() { + super(); + { + Module mod = new Module("", "queue", "", "", "", "1.0.0"); + mod.setFile(new File("")); + ModuleFactory.getStartedModulesMap().put(mod.getModuleId(), mod); + } + } + @Override public void updateSearchIndex() { // to prevent Data Filter's 'Illegal Record Access' diff --git a/api-2.3/src/test/java/org/openmrs/module/initializer/api/queues/QueueLoaderIntegrationTest.java b/api-2.3/src/test/java/org/openmrs/module/initializer/api/queues/QueueLoaderIntegrationTest.java new file mode 100644 index 000000000..b8eed537d --- /dev/null +++ b/api-2.3/src/test/java/org/openmrs/module/initializer/api/queues/QueueLoaderIntegrationTest.java @@ -0,0 +1,69 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.initializer.api.queues; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openmrs.module.initializer.DomainBaseModuleContextSensitive_2_3_Test; +import org.openmrs.module.queue.api.QueueService; +import org.openmrs.module.queue.model.Queue; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +public class QueueLoaderIntegrationTest extends DomainBaseModuleContextSensitive_2_3_Test { + + @Autowired + @Qualifier("queue.QueueService") + private QueueService queueService; + + @Autowired + private QueueLoader loader; + + @Before + public void setup() throws Exception { + executeDataSet("testdata/test-queues.xml"); + } + + @Test + public void load_shouldLoadAccordingToCsvFiles() throws Exception { + + // Initial Queue + { + Queue queue = queueService.getQueueByUuid("2a0e0eee-6888-11ee-ab8d-0242ac120002").orElse(null); + Assert.assertNotNull(queue); + Assert.assertEquals("Initial Queue", queue.getName()); + Assert.assertEquals("", queue.getDescription()); + Assert.assertEquals(2001, queue.getService().getConceptId().intValue()); + Assert.assertEquals(1, queue.getLocation().getLocationId().intValue()); + } + + loader.load(); + + // Revised Queue + { + Queue queue = queueService.getQueueByUuid("2a0e0eee-6888-11ee-ab8d-0242ac120002").orElse(null); + Assert.assertNotNull(queue); + Assert.assertEquals("Revised Queue", queue.getName()); + Assert.assertEquals("Revised Description", queue.getDescription()); + Assert.assertEquals(2002, queue.getService().getConceptId().intValue()); + Assert.assertEquals(2, queue.getLocation().getLocationId().intValue()); + } + // New Queue + { + Queue queue = queueService.getQueueByUuid("288db1cc-688a-11ee-ab8d-0242ac120002").orElse(null); + Assert.assertNotNull(queue); + Assert.assertEquals("New Queue", queue.getName()); + Assert.assertEquals("New Description", queue.getDescription()); + Assert.assertEquals(2001, queue.getService().getConceptId().intValue()); + Assert.assertEquals(3, queue.getLocation().getLocationId().intValue()); + } + } +} diff --git a/api-2.3/src/test/resources/testAppDataDir/configuration/queues/queues.csv b/api-2.3/src/test/resources/testAppDataDir/configuration/queues/queues.csv new file mode 100644 index 000000000..9df55879c --- /dev/null +++ b/api-2.3/src/test/resources/testAppDataDir/configuration/queues/queues.csv @@ -0,0 +1,3 @@ +Uuid,Void/Retire,Name,Description,Service,Location +2a0e0eee-6888-11ee-ab8d-0242ac120002,,Revised Queue,Revised Description,68b910bd-298c-4ecf-a632-661ae2f446op,Xanadu +288db1cc-688a-11ee-ab8d-0242ac120002,,New Queue,New Description,Triage,167ce20c-4785-4285-9119-d197268f7f4a diff --git a/api/src/main/java/org/openmrs/module/initializer/Domain.java b/api/src/main/java/org/openmrs/module/initializer/Domain.java index c4ae103ca..9f7ac0d3a 100644 --- a/api/src/main/java/org/openmrs/module/initializer/Domain.java +++ b/api/src/main/java/org/openmrs/module/initializer/Domain.java @@ -37,6 +37,7 @@ public enum Domain { APPOINTMENT_SPECIALITIES, APPOINTMENT_SERVICE_DEFINITIONS, APPOINTMENT_SERVICE_TYPES, + QUEUES, DATAFILTER_MAPPINGS, METADATA_SETS, METADATA_SET_MEMBERS, diff --git a/api/src/test/resources/testdata/test-queues.xml b/api/src/test/resources/testdata/test-queues.xml new file mode 100644 index 000000000..37016feb0 --- /dev/null +++ b/api/src/test/resources/testdata/test-queues.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/omod/src/main/resources/config.xml b/omod/src/main/resources/config.xml index 0577189fe..c1ed69e08 100644 --- a/omod/src/main/resources/config.xml +++ b/omod/src/main/resources/config.xml @@ -56,6 +56,9 @@ org.openmrs.module.fhir2 + + org.openmrs.module.queue + diff --git a/pom.xml b/pom.xml index 2477acc22..37ae77927 100644 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,7 @@ 1.0.0 + 1.0.0-SNAPSHOT 1.19.0 diff --git a/readme/queues.md b/readme/queues.md new file mode 100644 index 000000000..d8559b8d3 --- /dev/null +++ b/readme/queues.md @@ -0,0 +1,36 @@ +## Domain 'queues' +The **queues** subfolder contains CSV import files for saving queues in bulk. This is a possible example of its content: +```bash +queues/ + ├──queues.csv + └── ... +``` +There is currently only one format for the queue CSV line, here are the possible headers with a sample data set: + +|Uuid |Void/Retire |Name | Description | Service | Location | _order:1000 | +| - | - | - | - | - | +|32176576-1652-4835-8736-826eb0237482|| Clinical Consultation Queue | Consult Queue || Outpatient Service| Outpatient Clinic| + +Headers that start with an underscore such as `_order:1000` are metadata headers. The values in the columns under those headers are never read by the CSV parser. + +Let's review some important headers. + +###### Header `Name` *(mandatory)* +This is _not_ a localized header. +
The name is _not_ a secondary identifier to access a queue type. UUID must be provided for each Queue. + +###### Header `Description` +A description is optional and will populate the Queue description + +###### Header `Service` +This is a reference (UUID, same as mapping or name) to an existing Concept that defines the service associated with this Queue + +###### Header `Location` +This is a reference (UUID or name) to an existing Location that defines the Location associated with this Queue + +#### Requirements +* The [queue module](https://github.com/openmrs/openmrs-module-queue) must be installed +* The OpenMRS version must be 2.3 or higher + +#### Further examples: +Please look at the test configuration folder for sample import files for all domains, see [here](../api/src/test/resources/testAppDataDir/configuration). diff --git a/validator/pom.xml b/validator/pom.xml index ed78a858b..8ba3b2029 100644 --- a/validator/pom.xml +++ b/validator/pom.xml @@ -350,6 +350,14 @@ runtime jar
+ + + org.openmrs.module + queue-api + ${queueVersion} + runtime + jar + org.testcontainers