From b2685788e20ffff1bd4008cba48123a8bfb13b0d Mon Sep 17 00:00:00 2001 From: Michael Seaton Date: Mon, 23 Oct 2023 20:38:07 -0400 Subject: [PATCH 1/5] O3-2448 - Visit queue number customization --- .../module/queue/api/QueueEntryService.java | 17 +- .../queue/api/VisitQueueEntryService.java | 6 + .../module/queue/api/dao/QueueEntryDao.java | 9 - .../queue/api/dao/impl/QueueEntryDaoImpl.java | 46 ----- .../queue/api/impl/QueueEntryServiceImpl.java | 27 +-- .../api/impl/VisitQueueEntryServiceImpl.java | 37 ++-- .../module/queue/model/QueueEntry.java | 3 + .../BasicPatientQueueNumberGenerator.java | 69 +++++++ .../VisitAttributeQueueNumberGenerator.java | 100 ++++++++++ .../processor/VisitQueueEntryProcessor.java | 25 +++ api/src/main/resources/liquibase.xml | 13 ++ .../queue/api/dao/QueueEntryDaoTest.java | 15 -- .../TestPatientQueueNumberGenerator.java | 38 ++++ .../VisitQueueEntryProcessorTest.java | 186 ++++++++++++++++++ ...eueEntryDaoTest_conceptsInitialDataset.xml | 4 +- .../resources/QueueEntryNumberResource.java | 94 --------- 16 files changed, 473 insertions(+), 216 deletions(-) create mode 100644 api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java create mode 100644 api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java create mode 100644 api/src/main/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessor.java create mode 100644 api/src/test/java/org/openmrs/module/queue/processor/TestPatientQueueNumberGenerator.java create mode 100644 api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java delete mode 100644 omod/src/main/java/org/openmrs/module/queue/web/resources/QueueEntryNumberResource.java diff --git a/api/src/main/java/org/openmrs/module/queue/api/QueueEntryService.java b/api/src/main/java/org/openmrs/module/queue/api/QueueEntryService.java index 72499a2..427c92d 100644 --- a/api/src/main/java/org/openmrs/module/queue/api/QueueEntryService.java +++ b/api/src/main/java/org/openmrs/module/queue/api/QueueEntryService.java @@ -14,11 +14,7 @@ import java.util.Collection; import java.util.Optional; -import org.openmrs.Location; -import org.openmrs.Visit; -import org.openmrs.VisitAttributeType; import org.openmrs.api.APIException; -import org.openmrs.module.queue.model.Queue; import org.openmrs.module.queue.model.QueueEntry; public interface QueueEntryService { @@ -63,6 +59,11 @@ public interface QueueEntryService { */ void purgeQueueEntry(@NotNull QueueEntry queueEntry) throws APIException; + /** + * Return all QueueEntries that are active (non-voided, not ended) + */ + Collection getActiveQueueEntries(); + /** * Search for queue entries by conceptStatus * @@ -80,14 +81,6 @@ public interface QueueEntryService { */ Long getQueueEntriesCountByStatus(@NotNull String status); - /** - * @param location - * @param queue - * @return VisitQueueNumber - used to identify patients in the queue instead of using patient name - */ - String generateVisitQueueNumber(@NotNull Location location, @NotNull Queue queue, @NotNull Visit visit, - @NotNull VisitAttributeType visitAttributeType); - /** * Closes all active queue entries */ diff --git a/api/src/main/java/org/openmrs/module/queue/api/VisitQueueEntryService.java b/api/src/main/java/org/openmrs/module/queue/api/VisitQueueEntryService.java index ee74ad0..180bb76 100644 --- a/api/src/main/java/org/openmrs/module/queue/api/VisitQueueEntryService.java +++ b/api/src/main/java/org/openmrs/module/queue/api/VisitQueueEntryService.java @@ -12,10 +12,12 @@ import javax.validation.constraints.NotNull; import java.util.Collection; +import java.util.List; import java.util.Optional; import org.openmrs.api.APIException; import org.openmrs.module.queue.model.VisitQueueEntry; +import org.openmrs.module.queue.processor.VisitQueueEntryProcessor; public interface VisitQueueEntryService { @@ -111,4 +113,8 @@ Collection findVisitQueueEntries(String status, String service, */ Long getVisitQueueEntriesCountByLocationStatusAndService(@NotNull String status, String service, String locationUUid); + /** + * @param visitQueueEntryProcessors any VisitQueueEntryProcessor instances to set on the service + */ + void setVisitQueueEntryProcessors(List visitQueueEntryProcessors); } diff --git a/api/src/main/java/org/openmrs/module/queue/api/dao/QueueEntryDao.java b/api/src/main/java/org/openmrs/module/queue/api/dao/QueueEntryDao.java index 45b7b26..6b5879a 100644 --- a/api/src/main/java/org/openmrs/module/queue/api/dao/QueueEntryDao.java +++ b/api/src/main/java/org/openmrs/module/queue/api/dao/QueueEntryDao.java @@ -15,10 +15,8 @@ import java.util.List; import org.openmrs.Auditable; -import org.openmrs.Location; import org.openmrs.OpenmrsObject; import org.openmrs.api.ConceptNameType; -import org.openmrs.module.queue.model.Queue; import org.openmrs.module.queue.model.QueueEntry; public interface QueueEntryDao extends BaseQueueDao { @@ -44,13 +42,6 @@ Collection SearchQueueEntriesByConceptStatus(@NotNull String concept Long getQueueEntriesCountByConceptStatus(@NotNull String conceptStatus, ConceptNameType conceptNameType, boolean localePreferred); - /** - * @param location - * @param queue - * @return VisitQueueNumber - used to identify patients in the queue instead of using patient name - */ - String generateVisitQueueNumber(@NotNull Location location, @NotNull Queue queue); - /** * Gets active queue entries * diff --git a/api/src/main/java/org/openmrs/module/queue/api/dao/impl/QueueEntryDaoImpl.java b/api/src/main/java/org/openmrs/module/queue/api/dao/impl/QueueEntryDaoImpl.java index 477edde..0e3040e 100644 --- a/api/src/main/java/org/openmrs/module/queue/api/dao/impl/QueueEntryDaoImpl.java +++ b/api/src/main/java/org/openmrs/module/queue/api/dao/impl/QueueEntryDaoImpl.java @@ -9,29 +9,19 @@ */ package org.openmrs.module.queue.api.dao.impl; -import static org.hibernate.criterion.Restrictions.eq; - import javax.validation.constraints.NotNull; -import java.time.LocalDate; -import java.time.ZoneId; import java.util.Collection; -import java.util.Date; import java.util.List; -import org.apache.commons.lang3.StringUtils; import org.hibernate.Criteria; import org.hibernate.SessionFactory; -import org.hibernate.criterion.Conjunction; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Property; import org.hibernate.criterion.Restrictions; -import org.openmrs.Location; import org.openmrs.api.ConceptNameType; import org.openmrs.module.queue.api.dao.QueueEntryDao; -import org.openmrs.module.queue.model.Queue; import org.openmrs.module.queue.model.QueueEntry; -import org.openmrs.module.queue.model.VisitQueueEntry; import org.springframework.beans.factory.annotation.Qualifier; @SuppressWarnings("unchecked") @@ -74,42 +64,6 @@ public Long getQueueEntriesCountByConceptStatus(@NotNull String conceptStatus, C return (Long) criteria.uniqueResult(); } - @Override - public String generateVisitQueueNumber(Location location, Queue queue) { - Criteria criteriaVisitQueueEntries = getCurrentSession().createCriteria(VisitQueueEntry.class, "_vqe"); - includeVoidedObjects(criteriaVisitQueueEntries, false); - Criteria criteriaQueueEntries = criteriaVisitQueueEntries.createCriteria("_vqe.queueEntry", "_qe"); - Criteria criteriaQueue = criteriaQueueEntries.createCriteria("_qe.queue", "_q"); - Criteria criteriaQueueLocation = criteriaQueue.createCriteria("_q.location", "_ql"); - criteriaQueueLocation.add(eq("_ql.uuid", location.getUuid())); - criteriaQueueLocation.add(eq("_q.uuid", queue.getUuid())); - - LocalDate minDate = LocalDate.now(); - LocalDate maxDate = LocalDate.now().plusDays(1); - - Date startOfDay = Date.from(minDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); - Date endOfDay = Date.from(maxDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); - - Conjunction queueEntryStartedAtCheck = Restrictions.conjunction(); - queueEntryStartedAtCheck.add(Restrictions.ge("startedAt", startOfDay)); - queueEntryStartedAtCheck.add(Restrictions.lt("startedAt", endOfDay)); - criteriaQueueEntries.add(queueEntryStartedAtCheck); - - List queueEntryList = criteriaQueueLocation.list(); - - int visitQueueNumber = 1; - - if (!queueEntryList.isEmpty()) { - visitQueueNumber = queueEntryList.size() + 1; - } - - String paddedString = StringUtils.leftPad(String.valueOf(visitQueueNumber), 3, "0"); - - String serviceName = queue.getName().toUpperCase(); - String prefix = serviceName.length() < 3 ? serviceName : serviceName.substring(0, 3); - return prefix + "-" + paddedString; - } - /** * @see QueueEntryDao#getActiveQueueEntries() */ diff --git a/api/src/main/java/org/openmrs/module/queue/api/impl/QueueEntryServiceImpl.java b/api/src/main/java/org/openmrs/module/queue/api/impl/QueueEntryServiceImpl.java index a57a5ed..c7ffbce 100644 --- a/api/src/main/java/org/openmrs/module/queue/api/impl/QueueEntryServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/queue/api/impl/QueueEntryServiceImpl.java @@ -19,17 +19,12 @@ import lombok.AccessLevel; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.openmrs.Location; -import org.openmrs.Visit; -import org.openmrs.VisitAttribute; -import org.openmrs.VisitAttributeType; import org.openmrs.api.APIException; import org.openmrs.api.ConceptNameType; import org.openmrs.api.context.Context; import org.openmrs.api.impl.BaseOpenmrsService; import org.openmrs.module.queue.api.QueueEntryService; import org.openmrs.module.queue.api.dao.QueueEntryDao; -import org.openmrs.module.queue.model.Queue; import org.openmrs.module.queue.model.QueueEntry; import org.springframework.transaction.annotation.Transactional; @@ -91,6 +86,11 @@ public void purgeQueueEntry(QueueEntry queueEntry) throws APIException { this.dao.delete(queueEntry); } + @Override + public Collection getActiveQueueEntries() { + return dao.getActiveQueueEntries(); + } + /** * @see org.openmrs.module.queue.api.QueueEntryService#searchQueueEntriesByConceptStatus(String, * boolean) @@ -109,23 +109,6 @@ public Long getQueueEntriesCountByStatus(@NotNull String status) { return this.dao.getQueueEntriesCountByConceptStatus(status, ConceptNameType.FULLY_SPECIFIED, false); } - @Override - public String generateVisitQueueNumber(Location location, Queue queue, Visit visit, - VisitAttributeType visitAttributeType) { - if (location == null || queue == null || visit == null || visitAttributeType == null) { - throw new APIException("Sufficient parameters not supplied for generation of VisitQueueNumber"); - } - String queueNumber = dao.generateVisitQueueNumber(location, queue); - - // Create Visit Attribute using generated queue number - VisitAttribute visitQueueNumber = new VisitAttribute(); - visitQueueNumber.setAttributeType(visitAttributeType); - visitQueueNumber.setValue(queueNumber); - visit.setAttribute(visitQueueNumber); - Context.getVisitService().saveVisit(visit); - return queueNumber; - } - @Override public void closeActiveQueueEntries() { List queueEntries = dao.getActiveQueueEntries(); diff --git a/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java b/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java index e7fd498..3c847d1 100644 --- a/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java @@ -13,6 +13,7 @@ import java.util.Collection; import java.util.Date; +import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -30,13 +31,16 @@ import org.openmrs.module.queue.api.dao.VisitQueueEntryDao; import org.openmrs.module.queue.model.QueueEntry; import org.openmrs.module.queue.model.VisitQueueEntry; +import org.openmrs.module.queue.processor.VisitQueueEntryProcessor; import org.springframework.transaction.annotation.Transactional; @Slf4j @Transactional -@Setter(AccessLevel.MODULE) +@Setter(AccessLevel.PUBLIC) public class VisitQueueEntryServiceImpl extends BaseOpenmrsService implements VisitQueueEntryService { + private List visitQueueEntryProcessors; + private VisitQueueEntryDao dao; public void setDao(VisitQueueEntryDao dao) { @@ -49,23 +53,24 @@ public Optional getVisitQueueEntryByUuid(@NotNull String uuid) } @Override - public VisitQueueEntry createVisitQueueEntry(@NotNull VisitQueueEntry visitQueueEntry) { - //verify visit -patient & queue entry patient - //Todo more refactor - Visit visit = Context.getVisitService().getVisitByUuid(visitQueueEntry.getVisit().getUuid()); - Patient visitPatient = visit.getPatient(); - Patient queueEntryPatient = visitQueueEntry.getQueueEntry().getPatient(); - if (visitPatient != null & queueEntryPatient != null) { - boolean isPatientSame = visitPatient.getUuid().equals(queueEntryPatient.getUuid()); - if (!isPatientSame) { - throw new IllegalArgumentException("Patient mismatch - visit.patient does not match queueEntry.patient"); + public synchronized VisitQueueEntry createVisitQueueEntry(@NotNull VisitQueueEntry visitQueueEntry) { + Visit visit = visitQueueEntry.getVisit(); + Patient visitPatient = Context.getVisitService().getVisitByUuid(visit.getUuid()).getPatient(); + QueueEntry queueEntry = visitQueueEntry.getQueueEntry(); + if (queueEntry.getPatient() == null) { + queueEntry.setPatient(visitPatient); + } else if (!queueEntry.getPatient().getUuid().equals(visitPatient.getUuid())) { + throw new IllegalArgumentException("Patient mismatch - visit.patient does not match queueEntry.patient"); + } + queueEntry = Context.getService(QueueEntryService.class).createQueueEntry(queueEntry); + visitQueueEntry.setQueueEntry(queueEntry); + + if (visitQueueEntryProcessors != null) { + for (VisitQueueEntryProcessor processor : visitQueueEntryProcessors) { + processor.beforeSaveVisitQueueEntry(visitQueueEntry); } - QueueEntry newlyCreatedQueueEntry = Context.getService(QueueEntryService.class) - .createQueueEntry(visitQueueEntry.getQueueEntry()); - visitQueueEntry.setQueueEntry(newlyCreatedQueueEntry); - return this.dao.createOrUpdate(visitQueueEntry); } - return null; + return dao.createOrUpdate(visitQueueEntry); } /** diff --git a/api/src/main/java/org/openmrs/module/queue/model/QueueEntry.java b/api/src/main/java/org/openmrs/module/queue/model/QueueEntry.java index 074978d..6c8b5df 100644 --- a/api/src/main/java/org/openmrs/module/queue/model/QueueEntry.java +++ b/api/src/main/java/org/openmrs/module/queue/model/QueueEntry.java @@ -57,6 +57,9 @@ public class QueueEntry extends BaseChangeableOpenmrsData { @JoinColumn(name = "patient_id", nullable = false) private Patient patient; + @Column(name = "patient_queue_number") + private String patientQueueNumber; + @ManyToOne @JoinColumn(name = "priority", referencedColumnName = "concept_id", nullable = false) private Concept priority; diff --git a/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java b/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java new file mode 100644 index 0000000..def531e --- /dev/null +++ b/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.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.queue.processor; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.openmrs.module.queue.api.QueueEntryService; +import org.openmrs.module.queue.model.QueueEntry; +import org.openmrs.module.queue.model.VisitQueueEntry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +/** + * Basic implementation of a VisitQueueEntryProcessor which generates a patientQueueNumber prior to + * saving which: 1. If visit queue number is already populated, retain the existing value 2. + * Otherwise, find the highest numerical value of all currently active visit queue entries and add 1 + * Note: This assumes that the only consumer of this generator is the VisitQueueEntryService, which + * is synchronized + */ +@Slf4j +@Component +public class BasicPatientQueueNumberGenerator implements VisitQueueEntryProcessor { + + @Autowired + @Qualifier("queue.QueueEntryService") + QueueEntryService queueEntryService; + + /** + * This populates the given VisitQueueEntry with an appropriate patient queue number + */ + public void beforeSaveVisitQueueEntry(VisitQueueEntry visitQueueEntry) { + QueueEntry queueEntry = visitQueueEntry.getQueueEntry(); + if (StringUtils.isBlank(queueEntry.getPatientQueueNumber())) { + queueEntry.setPatientQueueNumber(generateNextQueueNumber()); + } + } + + /** + * @return the maximum patient queue number found in active queue entries that can be parsed into an + * int + */ + private String generateNextQueueNumber() { + int queueNum = 0; + for (QueueEntry qe : queueEntryService.getActiveQueueEntries()) { + if (qe.getPatientQueueNumber() != null) { + try { + int currentNum = Integer.parseInt(qe.getPatientQueueNumber()); + if (currentNum > queueNum) { + queueNum = currentNum; + } + } + catch (Exception e) { + log.debug("Unable to parse patient queue number into an int: " + qe.getPatientQueueNumber(), e); + } + } + } + queueNum += 1; + return Integer.toString(queueNum); + } + +} diff --git a/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java b/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java new file mode 100644 index 0000000..cf22cb1 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java @@ -0,0 +1,100 @@ +/* + * 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.queue.processor; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Date; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.openmrs.Location; +import org.openmrs.Visit; +import org.openmrs.VisitAttribute; +import org.openmrs.VisitAttributeType; +import org.openmrs.api.APIException; +import org.openmrs.api.AdministrationService; +import org.openmrs.api.VisitService; +import org.openmrs.module.queue.model.Queue; +import org.openmrs.module.queue.model.QueueEntry; +import org.openmrs.module.queue.model.VisitQueueEntry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * Implementation of a VisitQueueEntryProcessor which aims to retain legacy functionality using + * visit attributes + */ +@Slf4j +@Component +public class VisitAttributeQueueNumberGenerator implements VisitQueueEntryProcessor { + + @Autowired + VisitService visitService; + + @Autowired + AdministrationService adminService; + + /** + * This populates the given VisitQueueEntry with an appropriate patient queue number + */ + public void beforeSaveVisitQueueEntry(VisitQueueEntry visitQueueEntry) { + QueueEntry queueEntry = visitQueueEntry.getQueueEntry(); + Queue queue = queueEntry.getQueue(); + if (queue == null) { + throw new APIException("Queue is required"); + } + Location location = queue.getLocation(); + if (location == null) { + throw new APIException("Location is required"); + } + Visit visit = visitQueueEntry.getVisit(); + if (visit == null) { + throw new APIException("Visit is required"); + } + VisitAttributeType visitAttributeType = getVisitAttributeType(); + + LocalDate minDate = LocalDate.now(); + LocalDate maxDate = LocalDate.now().plusDays(1); + Date startOfDay = Date.from(minDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); + Date endOfDay = Date.from(maxDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); + int visitQueueNumber = 1; + for (QueueEntry qe : queue.getQueueEntries()) { + if (BooleanUtils.isNotTrue(qe.getVoided())) { + if (!qe.getStartedAt().before(startOfDay) && qe.getStartedAt().before(endOfDay)) { + visitQueueNumber++; + } + } + } + String paddedString = StringUtils.leftPad(String.valueOf(visitQueueNumber), 3, "0"); + String serviceName = queue.getName().toUpperCase(); + String prefix = serviceName.length() < 3 ? serviceName : serviceName.substring(0, 3); + String queueNumber = prefix + "-" + paddedString; + + // Associate this queue number directly + queueEntry.setPatientQueueNumber(queueNumber); + + // Create Visit Attribute using generated queue number + VisitAttribute visitAttribute = new VisitAttribute(); + visitAttribute.setAttributeType(visitAttributeType); + visitAttribute.setValueReferenceInternal(queueNumber); + visit.addAttribute(visitAttribute); + } + + private VisitAttributeType getVisitAttributeType() { + String gpName = "queue.visitQueueNumberAttributeUuid"; + String attributeType = adminService.getGlobalPropertyValue(gpName, ""); + if (StringUtils.isNotEmpty(attributeType)) { + return visitService.getVisitAttributeTypeByUuid(attributeType); + } + throw new APIException("Visit Attribute Type is required. Please configure global property: " + gpName); + } +} diff --git a/api/src/main/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessor.java b/api/src/main/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessor.java new file mode 100644 index 0000000..07a5e00 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessor.java @@ -0,0 +1,25 @@ +/* + * 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.queue.processor; + +import org.openmrs.module.queue.model.VisitQueueEntry; + +/** + * Implementations of this interface are able to add functionality into the VisitQueueEntry save + * process + */ +public interface VisitQueueEntryProcessor { + + /** + * This is called immediately prior saving a VisitQueueEntry to the database + */ + void beforeSaveVisitQueueEntry(VisitQueueEntry visitQueueEntry); + +} diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index 8acb6c6..e423f0c 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -385,4 +385,17 @@ schedulable_class = 'org.openmrs.module.queue.tasks.AutoCloseQueueEntryTask' + + + + + + + + Add column patient_queue_number to queue_entry table + + + + + diff --git a/api/src/test/java/org/openmrs/module/queue/api/dao/QueueEntryDaoTest.java b/api/src/test/java/org/openmrs/module/queue/api/dao/QueueEntryDaoTest.java index 557a071..b776964 100644 --- a/api/src/test/java/org/openmrs/module/queue/api/dao/QueueEntryDaoTest.java +++ b/api/src/test/java/org/openmrs/module/queue/api/dao/QueueEntryDaoTest.java @@ -10,7 +10,6 @@ package org.openmrs.module.queue.api.dao; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -25,12 +24,10 @@ import org.junit.Before; import org.junit.Test; import org.openmrs.Concept; -import org.openmrs.Location; import org.openmrs.Patient; import org.openmrs.api.ConceptNameType; import org.openmrs.api.context.Context; import org.openmrs.module.queue.SpringTestConfiguration; -import org.openmrs.module.queue.api.QueueEntryService; import org.openmrs.module.queue.model.Queue; import org.openmrs.module.queue.model.QueueEntry; import org.openmrs.test.BaseModuleContextSensitiveTest; @@ -244,16 +241,4 @@ public void shouldZeroCountQueueEntriesByBadStatus() { assertThat(queueEntriesCountByStatusCount, notNullValue()); assertThat(queueEntriesCountByStatusCount, is(0L)); } - - @Test - public void shouldGenerateVisitQueueNumber() { - QueueEntry queueEntry = Context.getService(QueueEntryService.class) - .getQueueEntryByUuid("7ub8fe43-2813-4kbc-80dc-2e5d30252cc5").get(); - Location location = Context.getLocationService().getLocationByUuid("d0938432-1691-11df-97a5-7038c098"); - - String queueNumber = dao.generateVisitQueueNumber(location, queueEntry.getQueue()); - - assertThat(queueNumber, notNullValue()); - assertThat(queueNumber, equalTo("CON-001")); - } } diff --git a/api/src/test/java/org/openmrs/module/queue/processor/TestPatientQueueNumberGenerator.java b/api/src/test/java/org/openmrs/module/queue/processor/TestPatientQueueNumberGenerator.java new file mode 100644 index 0000000..839c371 --- /dev/null +++ b/api/src/test/java/org/openmrs/module/queue/processor/TestPatientQueueNumberGenerator.java @@ -0,0 +1,38 @@ +/* + * 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.queue.processor; + +import lombok.extern.slf4j.Slf4j; +import org.openmrs.module.queue.model.VisitQueueEntry; +import org.springframework.stereotype.Component; + +/** + * Test class that allows delegating to a particular generator for a specific thread + */ +@Slf4j +@Component +public class TestPatientQueueNumberGenerator implements VisitQueueEntryProcessor { + + ThreadLocal processorToUse = new ThreadLocal<>(); + + /** + * This populates the given VisitQueueEntry with an appropriate patient queue number + */ + public void beforeSaveVisitQueueEntry(VisitQueueEntry visitQueueEntry) { + VisitQueueEntryProcessor processor = processorToUse.get(); + if (processor != null) { + processor.beforeSaveVisitQueueEntry(visitQueueEntry); + } + } + + public void setProcessorToUse(VisitQueueEntryProcessor visitQueueEntryProcessor) { + processorToUse.set(visitQueueEntryProcessor); + } +} diff --git a/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java b/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java new file mode 100644 index 0000000..26738c8 --- /dev/null +++ b/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java @@ -0,0 +1,186 @@ +/* + * 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.queue.processor; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.openmrs.Concept; +import org.openmrs.Patient; +import org.openmrs.Visit; +import org.openmrs.VisitAttributeType; +import org.openmrs.api.AdministrationService; +import org.openmrs.api.ConceptService; +import org.openmrs.api.PatientService; +import org.openmrs.api.VisitService; +import org.openmrs.api.context.Context; +import org.openmrs.customdatatype.datatype.FreeTextDatatype; +import org.openmrs.module.queue.SpringTestConfiguration; +import org.openmrs.module.queue.api.QueueEntryService; +import org.openmrs.module.queue.api.QueueService; +import org.openmrs.module.queue.api.VisitQueueEntryService; +import org.openmrs.module.queue.model.Queue; +import org.openmrs.module.queue.model.QueueEntry; +import org.openmrs.module.queue.model.VisitQueueEntry; +import org.openmrs.test.BaseModuleContextSensitiveTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = SpringTestConfiguration.class, inheritLocations = false) +public class VisitQueueEntryProcessorTest extends BaseModuleContextSensitiveTest { + + private static final List QUEUE_INITIAL_DATASET_XML = Arrays.asList( + "org/openmrs/module/queue/api/dao/QueueDaoTest_locationInitialDataset.xml", + "org/openmrs/module/queue/api/dao/QueueEntryDaoTest_conceptsInitialDataset.xml", + "org/openmrs/module/queue/api/dao/QueueDaoTest_initialDataset.xml", + "org/openmrs/module/queue/api/dao/QueueEntryDaoTest_patientInitialDataset.xml", + "org/openmrs/module/queue/api/dao/QueueEntryDaoTest_initialDataset.xml", + "org/openmrs/module/queue/api/dao/VisitQueueEntryDaoTest_visitInitialDataset.xml", + "org/openmrs/module/queue/api/dao/visitQueueEntryDaoTest_visitQueueNumberInitialDataset.xml", + "org/openmrs/module/queue/validators/QueueEntryValidatorTest_globalPropertyInitialDataset.xml"); + + @Autowired + AdministrationService adminService; + + @Autowired + PatientService patientService; + + @Autowired + VisitService visitService; + + @Autowired + @Qualifier("queue.QueueService") + QueueService queueService; + + @Autowired + @Qualifier("queue.QueueEntryService") + QueueEntryService queueEntryService; + + @Autowired + @Qualifier("queue.VisitQueueEntryService") + VisitQueueEntryService visitQueueEntryService; + + @Autowired + TestPatientQueueNumberGenerator testPatientQueueNumberGenerator; + + @Autowired + BasicPatientQueueNumberGenerator basicPatientQueueNumberGenerator; + + @Autowired + VisitAttributeQueueNumberGenerator visitAttributeQueueNumberGenerator; + + @Autowired + ConceptService conceptService; + + String visitQueueEntryUuid = "cd1d0825-71e6-11ee-af3b-0242ac120002"; + + Patient patient; + + Visit visit; + + Queue queue; + + Concept waitingStatus; + + Concept emergencyPriority; + + @Before + public void setup() { + QUEUE_INITIAL_DATASET_XML.forEach(this::executeDataSet); + patient = patientService.getPatient(100); + visit = visitService.getVisit(101); + queue = queueService.getQueueByUuid("3eb7fe43-2813-4kbc-80dc-2e5d30252bb5").get(); + waitingStatus = conceptService.getConcept(3001); + emergencyPriority = conceptService.getConcept(1001); + visitQueueEntryService.setVisitQueueEntryProcessors(Collections.singletonList(testPatientQueueNumberGenerator)); + + VisitAttributeType vat = new VisitAttributeType(); + vat.setName("Test"); + vat.setDatatypeClassname(FreeTextDatatype.class.getName()); + vat = visitService.saveVisitAttributeType(vat); + adminService.setGlobalProperty("queue.visitQueueNumberAttributeUuid", vat.getUuid()); + } + + private VisitQueueEntry newVisitQueueEntry() { + QueueEntry queueEntry = new QueueEntry(); + queueEntry.setUuid("5kb8fe43-2813-4kbc-80dc-2e5d30252cc87"); + queueEntry.setPatient(patient); + queueEntry.setQueue(queue); + queueEntry.setStartedAt(new Date()); + queueEntry.setStatus(waitingStatus); + queueEntry.setPriority(emergencyPriority); + VisitQueueEntry visitQueueEntry = new VisitQueueEntry(); + visitQueueEntry.setUuid(visitQueueEntryUuid); + visitQueueEntry.setQueueEntry(queueEntry); + visitQueueEntry.setVisit(visit); + return visitQueueEntry; + } + + @Test + public void shouldNotGenerateAVisitNumberIfNoProcessorsAreSpecified() { + testPatientQueueNumberGenerator.setProcessorToUse(null); + visitQueueEntryService.createVisitQueueEntry(newVisitQueueEntry()); + VisitQueueEntry visitQueueEntry = visitQueueEntryService.getVisitQueueEntryByUuid(visitQueueEntryUuid).get(); + assertThat(visitQueueEntry.getQueueEntry().getPatientQueueNumber(), nullValue()); + } + + @Test + public void shouldNotOverwriteAVisitNumberIfNoProcessorsAreSpecified() { + testPatientQueueNumberGenerator.setProcessorToUse(null); + VisitQueueEntry visitQueueEntry = newVisitQueueEntry(); + visitQueueEntry.getQueueEntry().setPatientQueueNumber("A1000"); + visitQueueEntryService.createVisitQueueEntry(visitQueueEntry); + visitQueueEntry = visitQueueEntryService.getVisitQueueEntryByUuid(visitQueueEntryUuid).get(); + assertThat(visitQueueEntry.getQueueEntry().getPatientQueueNumber(), equalTo("A1000")); + } + + @Test + public void shouldGenerateABasicVisitNumberIfProcessorIsSpecified() { + testPatientQueueNumberGenerator.setProcessorToUse(basicPatientQueueNumberGenerator); + visitQueueEntryService.createVisitQueueEntry(newVisitQueueEntry()); + VisitQueueEntry visitQueueEntry = visitQueueEntryService.getVisitQueueEntryByUuid(visitQueueEntryUuid).get(); + assertThat(visitQueueEntry.getQueueEntry().getPatientQueueNumber(), equalTo("1")); + } + + @Test + public void shouldGenerateAVisitAttributeVisitNumberIfProcessorIsSpecified() { + testPatientQueueNumberGenerator.setProcessorToUse(visitAttributeQueueNumberGenerator); + visitQueueEntryService.createVisitQueueEntry(newVisitQueueEntry()); + VisitQueueEntry visitQueueEntry = visitQueueEntryService.getVisitQueueEntryByUuid(visitQueueEntryUuid).get(); + assertThat(visitQueueEntry.getQueueEntry().getPatientQueueNumber(), nullValue()); + assertThat(visitQueueEntry.getVisit().getAttributes().iterator().next().getValueReference(), equalTo("TRI-002")); + } + + @Test + public void shouldGenerateVisitAttributeVisitNumberForConsultation() { + QueueEntry queueEntry = Context.getService(QueueEntryService.class) + .getQueueEntryByUuid("7ub8fe43-2813-4kbc-80dc-2e5d30252cc5").get(); + assertThat(queueEntry.getQueue().getLocation().getUuid(), equalTo("d0938432-1691-11df-97a5-7038c098")); + Visit visit = new Visit(); + visit.setPatient(queueEntry.getPatient()); + VisitQueueEntry visitQueueEntry = new VisitQueueEntry(); + visitQueueEntry.setQueueEntry(queueEntry); + visitQueueEntry.setVisit(visit); + visitAttributeQueueNumberGenerator.beforeSaveVisitQueueEntry(visitQueueEntry); + String queueNumber = visitQueueEntry.getVisit().getAttributes().iterator().next().getValueReference(); + assertThat(queueNumber, notNullValue()); + assertThat(queueNumber, equalTo("CON-001")); + } +} diff --git a/api/src/test/resources/org/openmrs/module/queue/api/dao/QueueEntryDaoTest_conceptsInitialDataset.xml b/api/src/test/resources/org/openmrs/module/queue/api/dao/QueueEntryDaoTest_conceptsInitialDataset.xml index fcdcad6..e74703b 100644 --- a/api/src/test/resources/org/openmrs/module/queue/api/dao/QueueEntryDaoTest_conceptsInitialDataset.xml +++ b/api/src/test/resources/org/openmrs/module/queue/api/dao/QueueEntryDaoTest_conceptsInitialDataset.xml @@ -13,8 +13,8 @@ - - + + diff --git a/omod/src/main/java/org/openmrs/module/queue/web/resources/QueueEntryNumberResource.java b/omod/src/main/java/org/openmrs/module/queue/web/resources/QueueEntryNumberResource.java deleted file mode 100644 index 9b967bf..0000000 --- a/omod/src/main/java/org/openmrs/module/queue/web/resources/QueueEntryNumberResource.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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.queue.web.resources; - -import java.util.Arrays; -import java.util.Optional; - -import org.openmrs.Location; -import org.openmrs.Visit; -import org.openmrs.VisitAttributeType; -import org.openmrs.api.context.Context; -import org.openmrs.module.queue.api.QueueEntryService; -import org.openmrs.module.queue.api.QueueService; -import org.openmrs.module.queue.model.Queue; -import org.openmrs.module.queue.web.resources.custom.response.GenericSingleObjectResult; -import org.openmrs.module.queue.web.resources.custom.response.PropValue; -import org.openmrs.module.queue.web.resources.custom.response.QueueEntryNumber; -import org.openmrs.module.webservices.rest.SimpleObject; -import org.openmrs.module.webservices.rest.web.RequestContext; -import org.openmrs.module.webservices.rest.web.RestConstants; -import org.openmrs.module.webservices.rest.web.annotation.Resource; -import org.openmrs.module.webservices.rest.web.representation.Representation; -import org.openmrs.module.webservices.rest.web.resource.api.PageableResult; -import org.openmrs.module.webservices.rest.web.resource.impl.DelegatingCrudResource; -import org.openmrs.module.webservices.rest.web.resource.impl.DelegatingResourceDescription; -import org.openmrs.module.webservices.rest.web.response.ResourceDoesNotSupportOperationException; -import org.openmrs.module.webservices.rest.web.response.ResponseException; - -@Resource(name = RestConstants.VERSION_1 - + "/queue-entry-number", supportedClass = QueueEntryNumber.class, supportedOpenmrsVersions = { "2.3 - 9.*" }) -public class QueueEntryNumberResource extends DelegatingCrudResource { - - @Override - public SimpleObject getByUniqueId(String uuid) { - throw new ResourceDoesNotSupportOperationException(); - } - - @Override - protected void delete(SimpleObject simpleObject, String s, RequestContext requestContext) throws ResponseException { - throw new ResourceDoesNotSupportOperationException(); - } - - @Override - public SimpleObject newDelegate() { - return new SimpleObject(); - } - - @Override - public SimpleObject save(SimpleObject simpleObject) { - throw new ResourceDoesNotSupportOperationException(); - } - - @Override - public void purge(SimpleObject simpleObject, RequestContext requestContext) throws ResponseException { - throw new ResourceDoesNotSupportOperationException(); - } - - @Override - public DelegatingResourceDescription getRepresentationDescription(Representation representation) { - return null; - } - - @Override - protected PageableResult doSearch(RequestContext requestContext) { - Location location = requestContext.getParameter("location") != null - ? Context.getLocationService().getLocationByUuid(requestContext.getParameter("location")) - : null; - Visit visit = requestContext.getParameter("visit") != null - ? Context.getVisitService().getVisitByUuid(requestContext.getParameter("visit")) - : null; - VisitAttributeType visitAttributeType = requestContext.getParameter("visitAttributeType") != null - ? Context.getVisitService().getVisitAttributeTypeByUuid(requestContext.getParameter("visitAttributeType")) - : null; - Optional queueOptional = Context.getService(QueueService.class) - .getQueueByUuid(requestContext.getParameter("queue")); - Queue queue = null; - if (queueOptional.isPresent()) { - queue = queueOptional.get(); - } - String visitQueueNumber = Context.getService(QueueEntryService.class).generateVisitQueueNumber(location, queue, - visit, visitAttributeType); - - return new GenericSingleObjectResult(Arrays.asList(new PropValue("serviceType", queue.getName()), - new PropValue("visitQueueNumber", visitQueueNumber))); - - } -} From e796bdbe8d9690a948c9e987a2e78e46db9a3805 Mon Sep 17 00:00:00 2001 From: Michael Seaton Date: Mon, 23 Oct 2023 21:15:55 -0400 Subject: [PATCH 2/5] O3-2448 - Visit queue number customization --- .../openmrs/module/queue/api/VisitQueueEntryService.java | 7 +++---- .../queue/api/impl/VisitQueueEntryServiceImpl.java | 9 +++------ .../processor/VisitAttributeQueueNumberGenerator.java | 2 +- .../queue/processor/VisitQueueEntryProcessorTest.java | 5 ++--- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/queue/api/VisitQueueEntryService.java b/api/src/main/java/org/openmrs/module/queue/api/VisitQueueEntryService.java index 180bb76..ea78384 100644 --- a/api/src/main/java/org/openmrs/module/queue/api/VisitQueueEntryService.java +++ b/api/src/main/java/org/openmrs/module/queue/api/VisitQueueEntryService.java @@ -12,7 +12,6 @@ import javax.validation.constraints.NotNull; import java.util.Collection; -import java.util.List; import java.util.Optional; import org.openmrs.api.APIException; @@ -108,13 +107,13 @@ Collection findVisitQueueEntries(String status, String service, * * @param service concept service name * @param status concept status name - * @param locaitonUuid location uuid + * @param locationUUid location uuid * @return {@link Long} count of visit queue entries */ Long getVisitQueueEntriesCountByLocationStatusAndService(@NotNull String status, String service, String locationUUid); /** - * @param visitQueueEntryProcessors any VisitQueueEntryProcessor instances to set on the service + * @param visitQueueEntryProcessor the visitQueueEntryProcessor to set */ - void setVisitQueueEntryProcessors(List visitQueueEntryProcessors); + void setVisitQueueEntryProcessor(VisitQueueEntryProcessor visitQueueEntryProcessor); } diff --git a/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java b/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java index 3c847d1..664708d 100644 --- a/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java @@ -13,7 +13,6 @@ import java.util.Collection; import java.util.Date; -import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -39,7 +38,7 @@ @Setter(AccessLevel.PUBLIC) public class VisitQueueEntryServiceImpl extends BaseOpenmrsService implements VisitQueueEntryService { - private List visitQueueEntryProcessors; + private VisitQueueEntryProcessor visitQueueEntryProcessor; private VisitQueueEntryDao dao; @@ -65,10 +64,8 @@ public synchronized VisitQueueEntry createVisitQueueEntry(@NotNull VisitQueueEnt queueEntry = Context.getService(QueueEntryService.class).createQueueEntry(queueEntry); visitQueueEntry.setQueueEntry(queueEntry); - if (visitQueueEntryProcessors != null) { - for (VisitQueueEntryProcessor processor : visitQueueEntryProcessors) { - processor.beforeSaveVisitQueueEntry(visitQueueEntry); - } + if (visitQueueEntryProcessor != null) { + visitQueueEntryProcessor.beforeSaveVisitQueueEntry(visitQueueEntry); } return dao.createOrUpdate(visitQueueEntry); } diff --git a/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java b/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java index cf22cb1..4ddc3d9 100644 --- a/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java +++ b/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java @@ -78,7 +78,7 @@ public void beforeSaveVisitQueueEntry(VisitQueueEntry visitQueueEntry) { String serviceName = queue.getName().toUpperCase(); String prefix = serviceName.length() < 3 ? serviceName : serviceName.substring(0, 3); String queueNumber = prefix + "-" + paddedString; - + // Associate this queue number directly queueEntry.setPatientQueueNumber(queueNumber); diff --git a/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java b/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java index 26738c8..900830b 100644 --- a/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java +++ b/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java @@ -15,7 +15,6 @@ import static org.hamcrest.Matchers.nullValue; import java.util.Arrays; -import java.util.Collections; import java.util.Date; import java.util.List; @@ -109,7 +108,7 @@ public void setup() { queue = queueService.getQueueByUuid("3eb7fe43-2813-4kbc-80dc-2e5d30252bb5").get(); waitingStatus = conceptService.getConcept(3001); emergencyPriority = conceptService.getConcept(1001); - visitQueueEntryService.setVisitQueueEntryProcessors(Collections.singletonList(testPatientQueueNumberGenerator)); + visitQueueEntryService.setVisitQueueEntryProcessor(testPatientQueueNumberGenerator); VisitAttributeType vat = new VisitAttributeType(); vat.setName("Test"); @@ -164,7 +163,7 @@ public void shouldGenerateAVisitAttributeVisitNumberIfProcessorIsSpecified() { testPatientQueueNumberGenerator.setProcessorToUse(visitAttributeQueueNumberGenerator); visitQueueEntryService.createVisitQueueEntry(newVisitQueueEntry()); VisitQueueEntry visitQueueEntry = visitQueueEntryService.getVisitQueueEntryByUuid(visitQueueEntryUuid).get(); - assertThat(visitQueueEntry.getQueueEntry().getPatientQueueNumber(), nullValue()); + assertThat(visitQueueEntry.getQueueEntry().getPatientQueueNumber(), equalTo("TRI-002")); assertThat(visitQueueEntry.getVisit().getAttributes().iterator().next().getValueReference(), equalTo("TRI-002")); } From 670794613c57359339929a137d32a3dbb075bf54 Mon Sep 17 00:00:00 2001 From: Michael Seaton Date: Mon, 23 Oct 2023 22:09:30 -0400 Subject: [PATCH 3/5] O3-2448 - Visit queue number customization --- .../api/impl/VisitQueueEntryServiceImpl.java | 1 + .../BasicPatientQueueNumberGenerator.java | 33 +------------------ .../VisitQueueEntryProcessorTest.java | 7 ++-- 3 files changed, 5 insertions(+), 36 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java b/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java index 664708d..fc7ac70 100644 --- a/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/queue/api/impl/VisitQueueEntryServiceImpl.java @@ -63,6 +63,7 @@ public synchronized VisitQueueEntry createVisitQueueEntry(@NotNull VisitQueueEnt } queueEntry = Context.getService(QueueEntryService.class).createQueueEntry(queueEntry); visitQueueEntry.setQueueEntry(queueEntry); + visitQueueEntry = dao.createOrUpdate(visitQueueEntry); if (visitQueueEntryProcessor != null) { visitQueueEntryProcessor.beforeSaveVisitQueueEntry(visitQueueEntry); diff --git a/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java b/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java index def531e..35daa1a 100644 --- a/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java +++ b/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java @@ -11,11 +11,8 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; -import org.openmrs.module.queue.api.QueueEntryService; import org.openmrs.module.queue.model.QueueEntry; import org.openmrs.module.queue.model.VisitQueueEntry; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; /** @@ -29,41 +26,13 @@ @Component public class BasicPatientQueueNumberGenerator implements VisitQueueEntryProcessor { - @Autowired - @Qualifier("queue.QueueEntryService") - QueueEntryService queueEntryService; - /** * This populates the given VisitQueueEntry with an appropriate patient queue number */ public void beforeSaveVisitQueueEntry(VisitQueueEntry visitQueueEntry) { QueueEntry queueEntry = visitQueueEntry.getQueueEntry(); if (StringUtils.isBlank(queueEntry.getPatientQueueNumber())) { - queueEntry.setPatientQueueNumber(generateNextQueueNumber()); + queueEntry.setPatientQueueNumber(Integer.toString(visitQueueEntry.getId())); } } - - /** - * @return the maximum patient queue number found in active queue entries that can be parsed into an - * int - */ - private String generateNextQueueNumber() { - int queueNum = 0; - for (QueueEntry qe : queueEntryService.getActiveQueueEntries()) { - if (qe.getPatientQueueNumber() != null) { - try { - int currentNum = Integer.parseInt(qe.getPatientQueueNumber()); - if (currentNum > queueNum) { - queueNum = currentNum; - } - } - catch (Exception e) { - log.debug("Unable to parse patient queue number into an int: " + qe.getPatientQueueNumber(), e); - } - } - } - queueNum += 1; - return Integer.toString(queueNum); - } - } diff --git a/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java b/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java index 900830b..baf3d60 100644 --- a/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java +++ b/api/src/test/java/org/openmrs/module/queue/processor/VisitQueueEntryProcessorTest.java @@ -28,7 +28,6 @@ import org.openmrs.api.ConceptService; import org.openmrs.api.PatientService; import org.openmrs.api.VisitService; -import org.openmrs.api.context.Context; import org.openmrs.customdatatype.datatype.FreeTextDatatype; import org.openmrs.module.queue.SpringTestConfiguration; import org.openmrs.module.queue.api.QueueEntryService; @@ -155,7 +154,8 @@ public void shouldGenerateABasicVisitNumberIfProcessorIsSpecified() { testPatientQueueNumberGenerator.setProcessorToUse(basicPatientQueueNumberGenerator); visitQueueEntryService.createVisitQueueEntry(newVisitQueueEntry()); VisitQueueEntry visitQueueEntry = visitQueueEntryService.getVisitQueueEntryByUuid(visitQueueEntryUuid).get(); - assertThat(visitQueueEntry.getQueueEntry().getPatientQueueNumber(), equalTo("1")); + assertThat(visitQueueEntry.getQueueEntry().getPatientQueueNumber(), + equalTo(Integer.toString(visitQueueEntry.getId()))); } @Test @@ -169,8 +169,7 @@ public void shouldGenerateAVisitAttributeVisitNumberIfProcessorIsSpecified() { @Test public void shouldGenerateVisitAttributeVisitNumberForConsultation() { - QueueEntry queueEntry = Context.getService(QueueEntryService.class) - .getQueueEntryByUuid("7ub8fe43-2813-4kbc-80dc-2e5d30252cc5").get(); + QueueEntry queueEntry = queueEntryService.getQueueEntryByUuid("7ub8fe43-2813-4kbc-80dc-2e5d30252cc5").get(); assertThat(queueEntry.getQueue().getLocation().getUuid(), equalTo("d0938432-1691-11df-97a5-7038c098")); Visit visit = new Visit(); visit.setPatient(queueEntry.getPatient()); From 0aa2b3a2cb02be27ffc1087d31bad8c4c680e66f Mon Sep 17 00:00:00 2001 From: Michael Seaton Date: Mon, 23 Oct 2023 22:12:01 -0400 Subject: [PATCH 4/5] O3-2448 - Visit queue number customization --- .../queue/processor/BasicPatientQueueNumberGenerator.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java b/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java index 35daa1a..1b97611 100644 --- a/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java +++ b/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java @@ -16,11 +16,8 @@ import org.springframework.stereotype.Component; /** - * Basic implementation of a VisitQueueEntryProcessor which generates a patientQueueNumber prior to - * saving which: 1. If visit queue number is already populated, retain the existing value 2. - * Otherwise, find the highest numerical value of all currently active visit queue entries and add 1 - * Note: This assumes that the only consumer of this generator is the VisitQueueEntryService, which - * is synchronized + * Basic implementation of a VisitQueueEntryProcessor which simply returns the + * primary kye of the VisitQueueEntry as a string. */ @Slf4j @Component From 4bd7ec33f4247bdd0211d46e12058c5a17dd7f05 Mon Sep 17 00:00:00 2001 From: Michael Seaton Date: Mon, 23 Oct 2023 22:15:32 -0400 Subject: [PATCH 5/5] O3-2448 - Visit queue number customization --- .../BasicPatientQueueNumberGenerator.java | 4 ++-- .../VisitAttributeQueueNumberGenerator.java | 15 +-------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java b/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java index 1b97611..3e6ec5e 100644 --- a/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java +++ b/api/src/main/java/org/openmrs/module/queue/processor/BasicPatientQueueNumberGenerator.java @@ -16,8 +16,8 @@ import org.springframework.stereotype.Component; /** - * Basic implementation of a VisitQueueEntryProcessor which simply returns the - * primary kye of the VisitQueueEntry as a string. + * Basic implementation of a VisitQueueEntryProcessor which simply returns the primary kye of the + * VisitQueueEntry as a string. */ @Slf4j @Component diff --git a/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java b/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java index 4ddc3d9..811705c 100644 --- a/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java +++ b/api/src/main/java/org/openmrs/module/queue/processor/VisitAttributeQueueNumberGenerator.java @@ -16,8 +16,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; -import org.openmrs.Location; -import org.openmrs.Visit; import org.openmrs.VisitAttribute; import org.openmrs.VisitAttributeType; import org.openmrs.api.APIException; @@ -49,17 +47,6 @@ public class VisitAttributeQueueNumberGenerator implements VisitQueueEntryProces public void beforeSaveVisitQueueEntry(VisitQueueEntry visitQueueEntry) { QueueEntry queueEntry = visitQueueEntry.getQueueEntry(); Queue queue = queueEntry.getQueue(); - if (queue == null) { - throw new APIException("Queue is required"); - } - Location location = queue.getLocation(); - if (location == null) { - throw new APIException("Location is required"); - } - Visit visit = visitQueueEntry.getVisit(); - if (visit == null) { - throw new APIException("Visit is required"); - } VisitAttributeType visitAttributeType = getVisitAttributeType(); LocalDate minDate = LocalDate.now(); @@ -86,7 +73,7 @@ public void beforeSaveVisitQueueEntry(VisitQueueEntry visitQueueEntry) { VisitAttribute visitAttribute = new VisitAttribute(); visitAttribute.setAttributeType(visitAttributeType); visitAttribute.setValueReferenceInternal(queueNumber); - visit.addAttribute(visitAttribute); + visitQueueEntry.getVisit().addAttribute(visitAttribute); } private VisitAttributeType getVisitAttributeType() {